更新联系人账号带来的问题及解决方法

Contact这个模块有一个feature:登陆XX账号以后,本地联系人会被转化到XX账号下。前两天同事在测试这个功能时发现一个问题:被转化的联系人无法被分享。
联系人分享一般需要先把联系人生成vcard。分析log发现,vcardComposer.init()失败了,init会调用

mCursor = mContentResolver.query(contentUri, projection, selection, selectionArgs, sortOrder);

而返回的mCursor.getCount() = 0

显然init中作为输入参数传入的contentUri是无效的。于是我追溯源头,看看这个contentUri是怎么生成的。在contact模块里发现这个:

final String lookupKey = mContactData.getLookupKey();
Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey);

这里的shareUri就是将要被分享的Uri地址,也就是最终传入vcardCompser的Uri。但是这个Uri拼接的语句看起来是没有问题的,lookupKey也确实是通过程序获取出来的。难道是getLookupKey()取错了?我把database导出来,查看了contacts这张表,再跟log里读出来的lookup比较,完全一致。lookup就是database里保存的字符串,Uri拼接方法也是对的,可为什么这个Uri就不能检索到对应的联系人呢?问题出在什么地方呢?

我仔细观察了database的几张表,又重新做了一次实验。我发现,登录XX账号以后,数据库里虽然account_id变了,但对应联系人的raw_contact表里的lookup字段并没有变化。我接着查看了XX账号同步的代码,发现是这样更新account_id的

getContentResolver().update(RawContacts.CONTENT_URI, updateValue, whereStr , selectionArgs1);

这句更新操作,不是直接操作raw_contacts表,而是view_raw_contacts视图,ContactProvider2会自动更加传入的字段,查询account表,再更新raw_contacts表的account_id。显然provider并没有顺便一起更新lookup,这就是问题所在了。

查看contactprovider的代码,lookup生成的规则是这样的。从而可见,lookup与accountType有关,如果accountType更新了,lookup必然也需要更新!

    public static void appendToLookupKey(StringBuilder lookupKey, String accountTypeWithDataSet,
            String accountName, long rawContactId, String sourceId,
            String displayName) {
        if (displayName == null) {
            displayName = "";
        }

        if (lookupKey.length() != 0) {
            lookupKey.append(".");
        }

        lookupKey.append(getAccountHashCode(accountTypeWithDataSet, accountName));
        if (sourceId == null) {
            lookupKey.append('r').append(rawContactId).append('-').append(
                    NameNormalizer.normalize(displayName));
        } else {
            int pos = lookupKey.length();
            lookupKey.append('i');
            if (appendEscapedSourceId(lookupKey, sourceId)) {
                lookupKey.setCharAt(pos, 'e');
            }
        }
    }

在contactsprovider2.java中updateRawContact(),如果value含有source_id字段就会触发对lookup的更新

if (values.containsKey(RawContacts.SOURCE_ID)) {
    mAggregator.get().updateLookupKeyForRawContact(db, rawContactId);
}

最终的解决方案就是在更新account_id的时候,传入一个空的source_id,从而触发lookup的更新。


总结:联系人是通过provider对database进行管理,如果修改联系人姓名,号码或者头像等等内容,provider会自动维护表项中诸如version, lookup等字段,从而保证功能正常运转。如果直接修改database的某一项内容,或者即使是使用了update这种方法对表里的特定内容进行修改,也可能导致provider对该联系人的管理失控。联系人的相关问题,尤其是程序更改了联系人database以后出现的问题,可以多从这个方面思考。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值