【问题标题】:How do you get contacts to aggregate properly when programmatically adding them?以编程方式添加联系人时,如何正确聚合联系人?
【发布时间】:2012-02-23 18:51:36
【问题描述】:

我看到this问答,但添加电话信息(甚至电子邮件)仍然无法正确汇总联系信息(当我检查人脉应用时,我可以看到同名下的多个条目) .

这是我用来测试它的代码。

//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();
    }
}

【问题讨论】:

  • 你有没有发现如何链接生成的联系人,即使他们的名字不同?
  • @androiddeveloper 抱歉,我停止了这方面的工作,从未找到好的答案
  • 好的,我想我用你的样本让它工作了,所以我发布了一个答案。问题是它让我想到了更多我不知道的问题。

标签: android contacts


【解决方案1】:

如果它们没有自动聚合,您可以通过在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);

【讨论】:

  • 那么我每次添加联系人时都需要应用这个吗?我正在开发的程序将添加大量联系人(其中一些或全部可能已经存在),这是否意味着对于我添加的每个联系人,我都必须查找所有具有相同 ID 的联系人的 ID命名并添加此异常?
  • 据我所知,情况相当严峻。我相信它们要么是自动聚合的,要么你必须强制它们。
  • 不得不四处走动并手动执行手机预期的操作似乎很愚蠢。我认为我添加联系人的方式一定有问题。
  • 注意:您一次只能聚合两个原始联系人。因此,如果用户执行了一些导致 4 个原始联系人的编辑操作,则您必须执行此聚合步骤 3 次。
【解决方案2】:

这是一个修改后的示例,包括链接,每个示例都有不同的数据,以证明它有效:

    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. 它如何决定替换哪些信息、添加哪些信息等...?
  4. 自动合并联系人的规则是什么?似乎相同的联系人姓名就足够了,但它可以在错误的情况下做到这一点(因为不同的人可以有相同的姓名,甚至包括姓氏)。
  5. 将“getLastPathSegment”用于原始联系人 ID 真的正确吗?

【讨论】:

    猜你喜欢
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多