New contact creating rather than updating existing contact
Asked Answered
P

2

2

I am integrating my app with android default Contacts application.I would like to show an option "xyz using MyApp" inside every Contacts Detail.I am able to see my app in Accounts Section with an option to sync Contacts but still my app not merging with existing contacts but instead creating a new contact and merging in it.

performSync() method

private static void addContact(ContentResolver contentResolver,int name, int phoneNumber) {
    Log.i("XYZ", "Adding contact: " + name);
    ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();

    //Create our RawContact
    ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI);
    builder.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, name);
    builder.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, "com.example.xyz.myapplication");
    builder.withValue(ContactsContract.RawContacts.SYNC1, phoneNumber);
    operationList.add(builder.build());

    //Create a Data record of common type 'StructuredName' for our RawContact
    builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
    builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
    builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
    builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
    operationList.add(builder.build());

    //Create a Data record of custom type "vnd.android.cursor.item/vnd.com.example.xyz.myapplication.profile" to display a link to the Last.fm profile
    builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
    builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
    builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.example.xyz.myapplication.profile");
    builder.withValue(ContactsContract.Data.DATA1, phoneNumber);
    builder.withValue(ContactsContract.Data.DATA2, "Last.fm Profile");
    builder.withValue(ContactsContract.Data.DATA3, "View profile");
    operationList.add(builder.build());

    try {
        contentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
    } catch (Exception e) {
        Log.e("XYZ", "Something went wrong during creation! " + e);
        e.printStackTrace();
    }
}
Platitude answered 20/10, 2018 at 11:36 Comment(4)
Can you explain what changes you made on the contacts service part and update contact part?Cretinism
@Cretinism I aggregate new contact with the existing contact using the code in accepted answer..Platitude
Is it possible to update your github project, so that I can compare the changes. It would be helpful for others also. Thanks in advance.Cretinism
@Cretinism The issue i was facing was that code in the question adds a new contact rather than updating an existing contact..and it's resolved by the code in accepted answer..Kindly let me know what issue you are facing so that I can help you!Platitude
M
3

in your addContact code you're missing the part that tells Contacts DB to join your new raw-contact into the existing contact, so that contact will now contain your raw-contact and your app-specific line will be shown when opening that contact in the contacts app.

Check this answer on how to join a RawContact into an existing Contact: why won't contacts aggregate?

You'll probably need to pass in some RawContact ID to your addContact method so it'll be able to join the two together.

UPDATE

Instead of applying the aggregation operation together with your RawContact insert operation, let's try to separate into two applyBatch calls, also, let's aggregate your new raw-contact with ALL existing raw-contacts, not just one of them. Try the following code, make sure you pass to it the existing contact-id (not raw-contact id) and your new raw-contact-id.

private void joinIntoExistingContact(long existingContactId, long newRawContactId) {

    // get all existing raw-contact-ids that belong to the contact-id
    List<Long> existingRawIds = new ArrayList<>();
    Cursor cur = getContentResolver().query(RawContacts.CONTENT_URI, new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=" + existingContactId, null, null);
    while (cur.moveToNext()) {
        existingRawIds.add(cur.getLong(0));
    }
    cur.close();
    Log.i("Join", "Found " + existingRawIds.size() + " raw-contact-ids");

    List<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

    // go over all existing raw ids, and join with our new one
    for (Long existingRawId : existingRawIds) {
        Builder builder = ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI);
        builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER);
        builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, newRawContactId);
        builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, existingRawId);
        ops.add(builder.build());
    }

    contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
}

P.S.
don't open two duplicate questions, one is enough.

ANOTHER UPDATE

You seem to have some confusion about IDs.

There are Data IDs, RawContact IDs, and Contact IDs.

CommonDataKinds.Phone._ID will return a Data ID, identifying the specific row in the Data table in which that phone number is stored.

You can get a from the Phone table the other IDs as well, use: CommonDataKinds.Phone.RAW_CONTACT_ID CommonDataKinds.Phone.CONTACT_ID

You can read more here: https://mcmap.net/q/911114/-contactscontract-select-records-by-phone-number

Militarism answered 22/10, 2018 at 7:18 Comment(12)
what is raw1 and raw2 and your answer link and how can i get that?Platitude
you need to obtain an existing raw-id of one of the raw-contacts of the contact you want to add your data to - that can be raw1, your new raw-contact's id can be raw2 (use can use builder.withValueBackReference(AggregationExceptions.RAW_CONTACT_ID2, 0))Militarism
I have updated question with the code i added after your answer in Update section and a link to github with my codePlatitude
always showing "Found 0 raw-contact-ids"..i getting existing id through -'cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID))';Platitude
is it possible you have some confusion on the difference between raw-contact-id and contact-id? if that's an existing contact it must have one or more raw contacts belonging to itMilitarism
I am using -getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null) to query contacts..can i get raw contact id through it?check my code for insertIconinContacts() in questionPlatitude
it's definitely NOT a contact-id, i'll add some info to my answerMilitarism
+1 for your answer..but I am facing 2 issues..1.Its showing app row for most contacts multiple times inside contact detail screen...2.For some contacts it not able to find the existing Id and creating a new contactPlatitude
@Militarism Hi How to generate newRawContactId?Cretinism
this is the id you're creating in your applyBatch call, you need to get the result from applyBatch (of type ContentProviderResult[]), then get the first index and extract the id from it, something like ContentUris.parseId(results[0])Militarism
@Militarism I am experiencing issue in few devices.For certain contacts I am seeing separate contact being created and my app icon is shown both in the existing and separate contacts.That means the new contact being created with addContact() method(in question) doesn't merge completely with existing contact inside joinIntoExistingContact() method.I tried debugging and found joinIntoExistingContact() method is executing fine and applyBatch() call doesn't throw any exception still the new contact doesn't merge completely with existing contact.Platitude
@Militarism I have posted question for that- #54051278Platitude
E
1

Try this here is the working code for me

MainActivity

public class MainActivity extends AppCompatActivity {

    private ArrayList<String> mNames = new ArrayList<>();
    private ArrayList<String> mIDs = new ArrayList<>();
    private ArrayList<String> mNumbers = new ArrayList<>();

    @SuppressLint("StaticFieldLeak")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                        != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123);

        } else {


//      Retrieve names from phone's contact list and save in mNames
            getContactDataBefore();

//      Apply changes to phone's contact list
            new AsyncTask<String, String, String>() {

                @Override
                protected String doInBackground(String... params) {
                    String name, number, id;
                    for (int i = 0; i < mIDs.size(); i++) {
//                    name = mNames.get(i);
                        id = mIDs.get(i);
                        number = mNumbers.get(i);
                        ContactsManager.addContact(MainActivity.this, new MyContact(id, number));
                    }
                    return null;
                }

                @Override
                protected void onPostExecute(String s) {
                    getContactDataAfter();
                }
            }.execute();
        }

    }

    private void getContactDataBefore() {
        int i = 0;

        // query all contact id's from device
        Cursor c1 = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
                new String[]{ContactsContract.Contacts._ID}, null, null, null);

        if ((c1 != null) && c1.moveToFirst()) {


            do {
                mIDs.add(c1.getString(c1.getColumnIndexOrThrow(ContactsContract.Contacts._ID)));

                i++;
            } while (c1.moveToNext() && i < c1.getCount());

            c1.close();

        }

        getPhoneNumber();
    }

    private void getPhoneNumber(){


        for (String data:mIDs){

            Cursor cursor = getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?",
                    new String[]{data}, null);

            while (cursor.moveToNext())
            {
                mNumbers.add(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
            }

            cursor.close();
        }

    }
    /**
     * Method to fetch contacts after updation (for logging purposes)
     */
    private void getContactDataAfter() {
        Cursor c = getContentResolver()
                .query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

        List<String> RIds = new ArrayList<>();
        mIDs = new ArrayList<>();
        mNumbers = new ArrayList<>();
        int i = 0;

        if (c != null && c.moveToFirst()) {
            do {
                mIDs.add(c.getString(c
                        .getColumnIndexOrThrow(ContactsContract.Contacts._ID)));
                mNames.add(c.getString(c
                        .getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)));

                Cursor c2 = getContentResolver()
                        .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                                new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER},
                                ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?",
                                new String[]{mIDs.get(i)}, null);

                if (c2 != null && c2.moveToFirst()) {
                    do {
                        mNumbers.add(c2.getString(c2
                                .getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)));
                    } while (c2.moveToNext());
                    c2.close();
                }

                Cursor rawcontacts = getContentResolver()
                        .query(ContactsContract.RawContacts.CONTENT_URI,
                                new String[]{ContactsContract.RawContacts._ID},
                                ContactsContract.RawContacts.CONTACT_ID + "=?",
                                new String[]{mIDs.get(i)}, null);

                if (rawcontacts != null && rawcontacts.moveToFirst()) {
                    do {
                        RIds.add(rawcontacts.getString(rawcontacts
                                .getColumnIndexOrThrow(ContactsContract.RawContacts._ID)));
                    } while (rawcontacts.moveToNext());
                    rawcontacts.close();
                }

                i++;
            } while (c.moveToNext());
            c.close();
        }
    }
}

AuthenticatorActivity

public class AuthenticatorActivity extends AccountAuthenticatorActivity {

    private AccountManager mAccountManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_authenticator);


        Intent res = new Intent();
        res.putExtra(AccountManager.KEY_ACCOUNT_NAME, Constants.ACCOUNT_NAME);
        res.putExtra(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
        res.putExtra(AccountManager.KEY_AUTHTOKEN, Constants.ACCOUNT_TOKEN);
        Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
        mAccountManager = AccountManager.get(this);
        mAccountManager.addAccountExplicitly(account, null, null);
//      mAccountManager.setAuthToken(account, Constants.AUTHTOKEN_TYPE_FULL_ACCESS, Constants.ACCOUNT_TOKEN);
        ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
        setAccountAuthenticatorResult(res.getExtras());
        setResult(RESULT_OK, res);
        finish();
    }
}

SyncAdapter

public class SyncAdapter extends AbstractThreadedSyncAdapter {

    private Context mContext;

    public SyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
        mContext = context;
    }

    @Override
    public void onPerformSync(Account account, Bundle extras, String authority,
                              ContentProviderClient provider, SyncResult syncResult) {
    }
}

SyncService

public class SyncService extends Service {

    private static final Object sSyncAdapterLock = new Object();
    private static SyncAdapter mSyncAdapter = null;

    @Override
    public void onCreate() {
        synchronized (sSyncAdapterLock){
            if(mSyncAdapter == null){
                mSyncAdapter = new SyncAdapter(getApplicationContext(),true);
            }
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mSyncAdapter.getSyncAdapterBinder();
    }
}

AuthenticationService

public class AuthenticationService extends Service {

    private static final String TAG = "AuthenticationService";
    private Authenticator mAuthenticator;

    @Override
    public void onCreate() {
        if (android.util.Log.isLoggable(TAG, android.util.Log.VERBOSE)) {
            android.util.Log.v(TAG, "SyncAdapter Authentication Service started.");
        }
        mAuthenticator = new Authenticator(this);
    }

    @Override
    public void onDestroy() {
        if (android.util.Log.isLoggable(TAG, android.util.Log.VERBOSE)) {
            Log.v(TAG, "SyncAdapter Authentication Service stopped.");
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "getBinder()...  returning the AccountAuthenticator binder for intent "
                    + intent);
        }
        return mAuthenticator.getIBinder();
    }
}

Authenticator

public class Authenticator extends AbstractAccountAuthenticator {

    private final Context mContext;

    public Authenticator(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
        return null;
    }

    @Override
    public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
        final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
        intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);

        final Bundle bundle = new Bundle();
        bundle.putParcelable(AccountManager.KEY_INTENT, intent);
        return bundle;
    }

    @Override
    public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
        final Bundle result = new Bundle();
        result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
        result.putString(AccountManager.KEY_ACCOUNT_TYPE, Constants.ACCOUNT_TYPE);
        return result;
    }

    @Override
    public String getAuthTokenLabel(String authTokenType) {
        return null;
    }

    @Override
    public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
        return null;
    }

    @Override
    public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
        return null;
    }
}

Constants

public class Constants {

    public static final String ACCOUNT_TYPE = "com.example.ajay.contacts_4";
    public static final String ACCOUNT_NAME = "Nilesh_Rathod";
    public static final String ACCOUNT_TOKEN = "733N";
}

ContactsManager

public class ContactsManager {

    private static String MIMETYPE = "vnd.android.cursor.item/com.example.ajay.contacts_4";


    public static void addContact(Context context, MyContact contact) {
        ContentResolver resolver = context.getContentResolver();
        boolean mHasAccount = isAlreadyRegistered(resolver, contact.Id);

        if (mHasAccount) {
            Log.I("Account is Exist");
        } else {

            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

            // insert account name and account type
            ops.add(ContentProviderOperation
                    .newInsert(addCallerIsSyncAdapterParameter(ContactsContract.RawContacts.CONTENT_URI, true))
                    .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, Constants.ACCOUNT_NAME)
                    .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE)
                    .withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
                            ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
                    .build());

            // insert contact number
            ops.add(ContentProviderOperation
                    .newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                    .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                    .withValue(CommonDataKinds.Phone.NUMBER, contact.number)
                    .build());


            // insert mime-type data
            ops.add(ContentProviderOperation
                    .newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Data.CONTENT_URI, true))
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                    .withValue(ContactsContract.Data.MIMETYPE, MIMETYPE)
                    .withValue(ContactsContract.Data.DATA1, 12345)
                    .withValue(ContactsContract.Data.DATA2, "Nilesh")
                    .withValue(ContactsContract.Data.DATA3, "ContactsDemo")
                    .build());


        }
    }

    /**
     * Check if contact is already registered with app
     */
    public static boolean isAlreadyRegistered(ContentResolver resolver, String id) {

        boolean isRegistered = false;
        List<String> str = new ArrayList<>();

        //query raw contact id's from the contact id
        Cursor c = resolver.query(RawContacts.CONTENT_URI, new String[]{RawContacts._ID},
                RawContacts.CONTACT_ID + "=?",
                new String[]{id}, null);

        //fetch all raw contact id's and save them in a list of string
        if (c != null && c.moveToFirst()) {
            do {
                str.add(c.getString(c.getColumnIndexOrThrow(RawContacts._ID)));
            } while (c.moveToNext());
            c.close();
        }

        //query account types and check the account type for each raw contact id
        for (int i = 0; i < str.size(); i++) {
            Cursor c1 = resolver.query(RawContacts.CONTENT_URI, new String[]{RawContacts.ACCOUNT_TYPE},
                    RawContacts._ID + "=?",
                    new String[]{str.get(i)}, null);

            if (c1 != null) {
                c1.moveToFirst();
                String accType = c1.getString(c1.getColumnIndexOrThrow(RawContacts.ACCOUNT_TYPE));
                if (accType != null && accType.equals("com.example.ajay.contacts_4")) {
                    isRegistered = true;
                    break;
                }
                c1.close();
            }
        }

        return isRegistered;
    }

    /**
     * Check for sync call
     */
    private static Uri addCallerIsSyncAdapterParameter(Uri uri, boolean isSyncOperation) {
        if (isSyncOperation) {
            return uri.buildUpon()
                    .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
                    .build();
        }
        return uri;
    }


}

authenticator.xml

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="com.example.ajay.contacts_4"
    android:icon="@drawable/icon"
    android:smallIcon="@drawable/icon"
    android:label="@string/app_name" />

contacts.xml

<?xml version="1.0" encoding="utf-8"?>
<ContactsSource
    xmlns:android="http://schemas.android.com/apk/res/android">
    <ContactsDataKind
        android:mimeType="vnd.android.cursor.item/com.example.ajay.contacts_4"
        android:icon="@drawable/icon"
        android:summaryColumn="data2"
        android:detailColumn="data3" />
</ContactsSource>

syncadapter.xml

<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
    android:contentAuthority="com.android.contacts"
    android:accountType="com.example.ajay.contacts_4"
    android:supportsUploading="false"
    android:userVisible="true" />

manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="neel.com.contactssyncingapp">

    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <service android:name=".utils.AuthenticationService" >
            <intent-filter>
                <action android:name="android.accounts.AccountAuthenticator" />
            </intent-filter>

            <meta-data
                android:name="android.accounts.AccountAuthenticator"
                android:resource="@xml/authenticator" />
        </service>

        <service android:name=".sync.SyncService" >
            <intent-filter>
                <action android:name="android.content.SyncAdapter" />
            </intent-filter>

            <meta-data
                android:name="android.content.SyncAdapter"
                android:resource="@xml/syncadapter" />
            <meta-data
                android:name="android.provider.CONTACTS_STRUCTURE"
                android:resource="@xml/contacts" />
        </service>

        <activity android:name=".activity.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>
        </activity>


        <activity
            android:name=".activity.ContactActivity"
            android:label="ContactActivity"
            android:screenOrientation="portrait"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.item/com.example.ajay.contacts_4" />
            </intent-filter>
        </activity>


        <activity android:name=".activity.AuthenticatorActivity" />
    </application>

</manifest>

OUTPUT

enter image description here

UPDATE

public class ContactActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contact);


        Uri intentData = getIntent().getData();
        if (!Uri.EMPTY.equals(intentData))
        {
            Cursor cursor = getContentResolver().query(intentData, null, null, null, null);
            if (cursor.moveToNext())
            {
                String username = cursor.getString(cursor.getColumnIndex("data2"));
                String number = cursor.getString(cursor.getColumnIndex("data3"));

                Log.e("USER_NAME",username);
                Log.e("USER_NUMBER",number);
            }
        }
    }
}
Esquibel answered 23/10, 2018 at 6:50 Comment(17)
Thanks..but for some contacts it is aggregating multiple times while for some contact it doesn't aggregate at all..I don't have regesteration condition as i want to aggregate with every contact..And shouldn't addContact() be called from inside onPerformSync()..u doing nothing inside onPerformSync()?Platitude
@BhuvneshVarma where is ContactActivity activity in your manifest fileEsquibel
@BhuvneshVarma you need to create a activity like ContactActivity in above manifest file to handle event when user click you app name in contactEsquibel
ContactActivity is the activity which should be open on click?I'll handle click later..first need to aggregate app properly with contacts?Platitude
Let us continue this discussion in chat.Esquibel
+1 for your answer..using AggregationException helps me to resolve that...how can I pass phone number to contact detail activity on clicking on an item?Platitude
@BhuvneshVarma check in my answer i have added that code (created that ContactActivity to open activity from contact ) let me know if any help reqiredEsquibel
@BhuvneshVarma check updated answer i have added code for ontactActivityEsquibel
@BhuvneshVarma have checked it??Esquibel
@BhuvneshVarma Can you update your github project so that I can also check what I'm missing?Cretinism
@BhuvneshVarma can u please update your code in github so it can help me to address mt mistake?Sears
@Prem kindly let me know what issue you are facing?Platitude
@BhuvneshVarma uisng above both answer and your AppContactSyncSample i'm able to create sync adapter but in contact list my app icon is not displaying i have done same thing mention in both above answers and your all comments but i can't find issue can u please share your code with us thank you for your responseSears
@Prem Is your code creating a new contact on synching rather than aggregating with the existing contact?Have you called contentResolver.applyBatch(ContactsContract.AUTHORITY, ops); and what result is it returning?Platitude
@Prem I understand that your code is for aggregating contact..but check if it is creating a new contact rather than aggregating..Also check what result applyBatch() is returning?Platitude
@Prem check what result applyBatch() is returning?debug code and try to find out the issue..If possible share your code in a new question so that i can check..The issue i was facing was that code in the question adds a new contact rather than updating an existing contact..and it's resolved by the code in accepted answer..your issue might be differentPlatitude
@Cretinism did you still required solution, because i found the solution for thisEsquibel

© 2022 - 2024 — McMap. All rights reserved.