当以编程方式添加联系人时,如何让联系人正确聚合?

我看到了这个问题和答案,但添加电话信息(甚至电子邮件)仍然不会导致联系人信息聚合正确(当我检查人应用程序,我可以看到同名多个条目)。

这里是我用来testing它的代码。

//get the account Account acct = null; Account[] accounts = AccountManager.get(getContext()).getAccounts(); for (Account acc : accounts){ acct = acc; }//assuming there's only one account in there (in my case I know there is) //loop a few times, creating a new contact each time. In theory, if they have the same name they should aggregate for(int i=0; i<3; i++){ ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, acct.type) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, acct.name) .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT) .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, "ContactName") .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "1234567890") .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, 1) .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Email.DATA, "email@address.com") .withValue(ContactsContract.CommonDataKinds.Email.TYPE, 1) .build()); try{ getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { Log.e("Contacts", "Something went wrong during creation! " + e); e.printStackTrace(); } } 

Solutions Collecting From Web of "当以编程方式添加联系人时,如何让联系人正确聚合?"

如果它们不是自动聚合,则可以通过向AggregationExceptions表添加一行来手动聚合它们。 请确保您注意到在文档中不允许插入。 你必须做一个更新。 现在我抓了两次。 下面的代码应该聚合ID为1和2的两个原始联系人:

 ContentValues cv = new ContentValues(); cv.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER); cv.put(AggregationExceptions.RAW_CONTACT_ID1, 1); cv.put(AggregationExceptions.RAW_CONTACT_ID2, 2); getContentResolver().update(AggregationExceptions.CONTENT_URI, cv, null, null); 

这里有一个修改后的示例,包括链接和每个不同的数据,以certificate它的工作原理:

  Account acct = null; Account[] accounts = AccountManager.get(this).getAccounts(); for (Account acc : accounts) { acct = acc; } //loop a few times, creating a new contact each time. In theory, if they have the same name they should aggregate final ArrayList<Uri> newlyCreatedContactsUris = new ArrayList<>(); for (int i = 0; i < 2; i++) { ArrayList<ContentProviderOperation> ops = new ArrayList<>(); ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, acct == null ? null : acct.type) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, acct == null ? null : acct.name) .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT) .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, "ContactName" + i) .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, Integer.toString(123456789 * (i + 1))) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, 1) .build()); ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Email.DATA, "email" + i + "@address.com") .withValue(ContactsContract.CommonDataKinds.Email.TYPE, 1) .build()); try { final ContentProviderResult[] contentProviderResults = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); newlyCreatedContactsUris.add(contentProviderResults[0].uri); Log.d("AppLog", "done creating new contacts data"); } catch (Exception e) { Log.e("AppLog", "Something went wrong during creation! " + e); e.printStackTrace(); } } //Note: seems we can only link 2 contacts data together, not more ArrayList<ContentProviderOperation> mergeOps = new ArrayList<>(); mergeOps.add(ContentProviderOperation.newUpdate(ContactsContract.AggregationExceptions.CONTENT_URI) .withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER) .withValue(AggregationExceptions.RAW_CONTACT_ID1, newlyCreatedContactsUris.get(0).getLastPathSegment()) .withValue(AggregationExceptions.RAW_CONTACT_ID2, newlyCreatedContactsUris.get(1).getLastPathSegment()) .build()); try { final ContentProviderResult[] contentProviderResults2 = getApplicationContext().getContentResolver().applyBatch(ContactsContract.AUTHORITY, mergeOps); Log.d("AppLog", "done merging"); } catch (RemoteException e) { e.printStackTrace(); } catch (OperationApplicationException e) { e.printStackTrace(); } 

结果是:

在这里输入图像说明

我不确定的是:

  1. 如何获得现有的联系人数据,然后决定哪些合并? 我注意到,内置的联系人应用程序可以合并联系人,但有时不会把它们合并,当主要联系人将采取合并的名称。 我该怎么做?
  2. 如何进入联系人应用程序,没有选项来取消链接,而不是使用UI做同样的事情?
  3. 它如何决定要replace的信息,要添加哪些信息等等?
  4. 自动合并联系人的规则是什么? 看起来相同的联系人名字就够了,但是可以在错误的情况下进行(因为不同的人可以有相同的名字,甚至包括姓)。
  5. 对于原始联系人ID使用“getLastPathSegment”是否真的是正确的方法?