androidcontactsaggregationrawcontacts

Add RawContact so it aggregates to an existing contact


I am trying to add a new RawContact to an existing Contact so my custom data field shows up inside the original Contact. I tried Adding a StructuredName Data row to my new RawContact with a DisplayName that matches the DisplayName of the original RawContact. I thought matching DisplayNames would be enough to aggregate both RawContacts but the contacts app seems to display both RawContacts as different Contacts.

Here is my code

  public static void addContact(Context context, Account account, String number, String displayname) {
    Log.e(Global.TAG, "adding contact: " + number + " / " + displayname);

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

    //Create our RawContact
    ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
    builder.withValue(RawContacts.ACCOUNT_NAME, account.name);
    builder.withValue(RawContacts.ACCOUNT_TYPE, account.type);

    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, displayname);
    operationList.add(builder.build());

    //Create a Data record of custom type "vnd.android.cursor.item/vnd.be.ourservice.profile" to display a link to the     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.be.ourservice.profile");
    builder.withValue(ContactsContract.Data.DATA1, number);
    builder.withValue(ContactsContract.Data.DATA2, "ourservice user");
    builder.withValue(ContactsContract.Data.DATA3, "Go to ourservice profile");
    operationList.add(builder.build());



    try {
     mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
     Log.d(Global.TAG, "addContact batch applied");
    } catch (Exception e) {
     Log.e(Global.TAG, "Something went wrong during creation! " + e);
     e.printStackTrace();
    }
   }

Solution

  • I figured it out. I tried replacing the CommonDataKinds.StructuredName row with a CommonDataKinds.Phone row that contains the same number as my original contact and then it aggregates the RawContacts correctly.

    The working code looks like this

    public static void addContactTag(Context context, Account account, String number) {
    
        ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
    
        //  Create our RawContact                                                                                                           
        ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
        builder.withValue(RawContacts.ACCOUNT_NAME, account.name);
        builder.withValue(RawContacts.ACCOUNT_TYPE, account.type);
        operationList.add(builder.build());
    
        //  Create a Data record of common type 'Phone' for our RawContact                                                                  
        builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
        builder.withValueBackReference(Data.RAW_CONTACT_ID, 0);
        builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
        builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, number);
        operationList.add(builder.build());
    
        //Create a Data record of custom type "vnd.android.cursor.item/vnd.be.ourservice.profile" to display a link to our     profile    
        builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
        builder.withValueBackReference(Data.RAW_CONTACT_ID, 0);
        builder.withValue(ContactsContract.Data.MIMETYPE, OURSERVICE_MIMETYPE);
        builder.withValue(ContactsContract.Data.DATA1, number);
        builder.withValue(ContactsContract.Data.DATA2, "ourservice user");
        builder.withValue(ContactsContract.Data.DATA3, "Go to ourservice profile");
        operationList.add(builder.build());
    
    
        try {
            mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
            Log.d(Global.TAG, "addContact batch applied");
        } catch (Exception e) {
            Log.e(Global.TAG, "Something went wrong during creation! " + e);
            e.printStackTrace();
        }
    }