android - 为什么 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?
以下是我已经知道的事情:
- 无论联系人提供者处理的来源如何,重复条目的联系人 ID 都是相同的。看看这个ContactsAggregator
- Contact 表有一列
name_raw_contact_id
给出 RawContacts 表的相应 _ID(但是我不确定这是否可以被视为 RawContacts 表中联系人的主要条目)。
下面列出了我想知道的事情:
- 我们可以从
ContactsContract.Contact
表中获取唯一的联系人,但是为了使用联系人提供者修改/删除数据值(如电话、电子邮件等),我们可以选择哪个 raw_contact_id ?或者我可以直接在ContactContract.Data
表格中进行修改。 - whatsapp 如何检测联系人的添加/修改。据我所知,联系人提供者不提供
_ID
新的联系人添加。他们是在每次应用启动后还是以相同的时间间隔刷新联系人列表? - 如何获取联系人的原始来源(在我的情况下可能是 gmail/native)并省略使用联系人提供商的应用程序(如 Duo、skype、whatsapp)创建的副本。
如果有人帮助我理解这一点,那就太好了。随意推荐我可以询问这些问题的任何其他频道
解决方案
投影确实不正确。
联系人数据库由三个主要表组成:
Contacts
- 每个条目代表一个联系人,并将一个或多个组合在一起RawContacts
RawContacts
- 每个条目代表一些SyncAdapter
(例如 Whatsapp、Google、Facebook、Viber)同步的联系人数据,这将多个数据条目分组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
推荐阅读
- typescript - 试图用打字稿和回溯解决数独的错误
- r - ggplot2 图例,每个其他分组都有轮廓
- javascript - 如何在 React-Native 复选框中更改背景颜色透明?
- javascript - Django:带有 javascript 的模态框
- html - 在 Bootstrap 上更改导航栏的颜色
- c - 在按钮单击时选择用户的选择
- google-cloud-platform - 将对象上传到 Google Cloud Bucket 时出现 404 错误
- c - 我是否正确实施了 copy_from_user?
- django - 我们如何在不使用 Relay 功能的情况下在 graphene-django 项目的 schema.py 中进行过滤查询?
- ios - 为什么要设置一个随后不使用的常量