首页 > 解决方案 > 为什么 Duo、whatsapp、skype 等应用在原生联系人的 RawContact 表中有条目

问题描述

我正在使用 ContactContracts API 来获取 RawContacts 表中的条目

private void fetchRawContactEntries() {
        String [] mProjectionColumns = new String [] {
            RawContacts.CONTACT_ID, RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE, RawContacts.DISPLAY_NAME_PRIMARY
        };

        Cursor c = getContentResolver().query(RawContacts.CONTENT_URI, mProjectionColumns, null, null,
                RawContacts.DISPLAY_NAME_PRIMARY + " ASC");
        if(c != null) {
            while(c.moveToNext()) {
                long contactId = c.getLong(0);
                String accountName = c.getString(1);
                String accountType = c.getString(2);
                String displayName = c.getString(3);

                Log.d("Logs", contactId +  ", accountName:" + accountName + ", Display Name : " + displayName);
            }
        }
    }

我观察到每个联系人在 raw_contacts 表中有多个条目。(Gmail、Duo 等)

2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs:2227,帐户名:kartikayemail@gmail.com,显示名称:Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:WhatsApp, Display Name: Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:Duo, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2227, accountName:Duo, Display Name : Abhay Y
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:kartik@gmail.com, Display Name : Abhayuday
2019-05-28 19:21:15.483 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName:WhatsApp, Display Name : Abhayuday
2019-05-28 19:21:15.484 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName: Duo, Display Name : Abhayuday
2019-05-28 19:21:15.484 5458-5458/com.example.kartikaysingh.cs D/Logs: 2140, accountName: Duo, Display Name : Abhayuday

事实上,在RawContactDuo表中创建了两个不同的条目。应用程序如何native contact区分这些条目。
我知道他们显示了Contacts 表的条目,但是在修改他们选择的 raw_contact_id 数据时Duo or Whatsapp or gmail。他们从哪里得到这些原始的 raw_contact_id

以下是我已经知道的事情:

  1. 无论联系人提供者处理的来源如何,重复条目的联系人 ID 都是相同的。看看这个ContactsAggregator
  2. Contact 表有一列name_raw_contact_id给出 RawContacts 表的相应 _ID(但是我不确定这是否可以被视为 RawContacts 表中联系人的主要条目)。

下面列出了我想知道的事情:

  1. 我们可以从ContactsContract.Contact表中获取唯一的联系人,但是为了使用联系人提供者修改/删除数据值(如电话、电子邮件等),我们可以选择哪个 raw_contact_id ?或者我可以直接在ContactContract.Data表格中进行修改。
  2. whatsapp 如何检测联系人的添加/修改。据我所知,联系人提供者不提供_ID新的联系人添加。他们是在每次应用启动后还是以相同的时间间隔刷新联系人列表?
  3. 如何获取联系人的原始来源(在我的情况下可能是 gmail/native)并省略使用联系人提供商的应用程序(如 Duo、skype、whatsapp)创建的副本。

如果有人帮助我理解这一点,那就太好了。随意推荐我可以询问这些问题的任何其他频道

标签: androidandroid-contacts

解决方案


投影确实不正确。

联系人数据库由三个主要表组成:

  1. Contacts- 每个条目代表一个联系人,并将一个或多个组合在一起RawContacts
  2. RawContacts- 每个条目代表一些SyncAdapter(例如 Whatsapp、Google、Facebook、Viber)同步的联系人数据,这将多个数据条目分组
  3. Data- 关于联系人、电子邮件、电话等的实际数据。每一行都是属于单个数据的单个数据RawContact

Google Play 上具有足够权限的每个应用程序都可以添加新联系人或新 RawContact 并将其聚合到现有联系人中,就像 Whatsapp / Duo 一样,这允许每个应用程序存储有关特定联系人的信息,例如它的 Whatsapp ID 或任何对应用程序有用的其他信息。

您有一个错误的假设,即只有一个“主要” RawContact 是重要的,而其他的都附加在它上面。相反,代表单个联系人的 RawContacts 列表可以包含多个同等重要的 Google RawContacts,或者根本没有 Google RawContacts,有一个区别可以帮助您选择 RawContact 进行编辑,即 RawContacts 是否由该应用程序是只读或可写的。

下面是遍历设备上所有帐户的代码,并查看哪些是只读的,哪些是可修改的 ( supportsUploading):

final SyncAdapterType[] syncs = ContentResolver.getSyncAdapterTypes();
for (SyncAdapterType sync : syncs) {
    Log.d(TAG, "found SyncAdapter: " + sync.accountType);
    if (ContactsContract.AUTHORITY.equals(sync.authority)) {
        Log.d(TAG, "found SyncAdapter that supports contacts: " + sync.accountType);
        if (sync.supportsUploading()) {
            Log.d(TAG, "found SyncAdapter that supports contacts and is not read-only: " + sync.accountType);
            // we'll now get a list of all accounts under that accountType:
            Account[] accounts = AccountManager.get(this).getAccountsByType(sync.accountType);
            for (Account account : accounts) {
               Log.d(TAG, account.type + " / " + account.name);
            }
        }
    }
}

探索其他可能对您有帮助的好SyncAdapterType东西。isUserVisible


推荐阅读