使用ContentProviderOperation更新和插入联系人

10

我在 Android 2.0+ 上更新/插入联系人时遇到了问题。 当通讯录为空时插入新联系人没有问题,但当我第二次插入时, TEL、EMAIL 等字段会出现重复和三倍的情况,但是 N、FN、ORG 是正常的(只有一个副本)。

在得到了该论坛其他成员的建议之后,我首先更新了一个联系人,然后 ContentProviderResult[] 返回了空的 uri,然后我执行了插入操作,这一步执行得很好。但是之后我进行了更新,所有联系人都聚合成了一个 - 我得到了一个存在于通讯录中的联系人而不是原来的3个。这个联系人已经损坏了,联系人字段是随机生成的。

我设置了 Google 账户。

代码:

ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
  ops.add(ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI)
    .withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED)
    .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
    .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
    .build()); 

// add name
ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
   builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
   builder.withValue(ContactsContract.Data.MIMETYPE,
     ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.PHONETIC_FAMILY_NAME, name);

// phones
ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);
   builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
   builder.withValue(ContactsContract.Data.MIMETYPE,
     ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
   builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneValue);
   builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType);
   builder.withValue(ContactsContract.CommonDataKinds.Phone.LABEL, phoneLabel);         
   ops.add(builder.build());

// emails ...
// orgs ...

try {

  ContentProviderResult[]  result = mContentResolver.applyBatch(ContactsContract.AUTHORITY, ops);   
 }
  } catch (Exception e) {
   Log.e(LOG_TAG, "Exception while contact updating: " + e.getMessage());
  }

这个解决方案有什么问题?聚合引擎是如何工作的?

我会很高兴得到帮助。

Bogus

3个回答

2
如果您想进行更新操作,每个ContentProviderOperation都必须提供where子句。详见此处此处。请注意保留HTML标签。

1

我遇到了同样的问题。我认为应该这样做才能解决。

opt.add(ContentProviderOperation.newUpdate(ContactsContract.Contacts.CONTENT_URI)
                .withSelection(ContactsContract.Contacts._ID, new String[]{entity.getPeople()})
                .withValue(ContactsContract.Contacts.DISPLAY_NAME, "daerba")
                .build()
        );

但是出了问题并报告了这个错误。

android.database.sqlite.SQLiteException:绑定或列索引超出范围

我认为必须有一个选择来更新联系人。因此,使用withSelection很重要,以告诉ContentResolver要更新哪个联系人。

希望这能提供一些线索。


4
如果使用withSelection方法,需要在String[]中用'?'来表示参数。<br/> 例如:.withSelection(ContractsContract.Contacts._ID + " = ?", new String[] {"5"})<br/>如果没有使用'?'来绑定String[]的值,那么这些值将不会被绑定。 - jt-gilkeson
@wiseideal 感谢您指引我正确的方向。withSelection 一定是我的问题所在。 - Bwire

0

你正在重新定义构建器,但没有将其添加到操作中,因此数据从未被发送到名称,这就解释了为什么你的聚合如此奇怪。

// add name
ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);

// phones
ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI);

另外,由于可读性的原因,我更喜欢在处理较小批次时使用以下格式...

ArrayList<ContentProviderOperation> batchOp = new ArrayList<ContentProviderOperation>();
batchOp.add(ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI) 
            .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
            .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType).build());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接