获取 Android 手机联系人的跨设备唯一 ID
Posted
技术标签:
【中文标题】获取 Android 手机联系人的跨设备唯一 ID【英文标题】:Get cross-device unique ID for Android phone contacts 【发布时间】:2020-01-26 20:04:03 【问题描述】:我需要从 android 设备查询我正在处理的项目的联系人,并且我需要以我可以将应用程序中的实例链接到电话簿中的联系人的方式保存它们。 我发现每个联系人的CONTACT_ID(这是对_ID的引用)可能会在设备之间发生变化,所以如果我切换到其他Android设备,该ID将无效。 一个临时解决方案是使用联系人的SOURCE_ID,它是一个字符串,用于将该行唯一标识到其源帐户。解决方案非常好,因为如果联系人来自(例如)Google 帐户,它将在我拥有的每台设备上保持完全相同的 ID。问题是 - 并非每个联系人都有 SOURCE_ID。 也可以使用它的数据作为过滤器来查询特定的联系人,它可以作为一个唯一的 ID,例如他的电话号码等......但是每条数据都有缺陷。例如:一个联系人可能有多个电话号码(这仍然可以)并且号码可以变化(例如:202-555-0105 与 +1-202-555-0105 相同,也与 ( 202) 555 0105 和 2025550105)。编辑:也不是每个联系人都有电话号码,那又如何呢?
所以在给出问题之后 -我怎样才能为 Android 电话簿中的联系人获取一个唯一 ID,这样他们就可以跨设备使用?
注意:默认情况下可以在 ios 上使用(请参阅documentation)-
代表同一个人的不同帐户中的联系人可能会自动链接在一起。链接的联系人在 OS X 和 iOS 应用程序中显示为统一联系人。统一联系人是合并到一个联系人中的一组链接联系人的内存中临时视图。
默认情况下,联系人框架返回统一联系人。每个获取的统一联系人 (CNContact) 对象都有自己的唯一标识符,该标识符不同于链接联系人集中任何单个联系人的标识符。应使用其标识符重新获取统一联系人。
【问题讨论】:
【参考方案1】:你要找的是LOOKUP_KEY
一个不透明的值,其中包含有关如何在其行 ID 由于同步或聚合而更改时查找联系人的提示。
要让联系人LOOKUP_KEY
循环访问您的联系人,下面是一个示例:
注意:<uses-permission android:name="android.permission.READ_CONTACTS" />
是必需的。
val contentUri = ContactsContract.Contacts.CONTENT_URI
val cursor = context?.contentResolver?.query(contentUri, null, null, null, null)
if (cursor != null)
while (cursor.moveToNext())
val id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
val name =
cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY))
val lookupKey =
cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
cursor?.close()
以下是使用LOOKUP_KEY
检索联系人的方法:
val lookupKey = "0r1-3C263544104632"
val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
val uri = ContactsContract.Contacts.lookupContact(contentResolver, lookupUri)
val cursor = context?.contentResolver?.query(uri, null, null, null, null)
if (cursor != null)
while (cursor.moveToNext())
val id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
val name =
cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME_PRIMARY))
cursor?.close()
请注意,必须同步联系人才能避免重新生成LOOKUP_KEY
。
保证为每个联系人生成LOOKUP_KEY
,但是,如果未设置帐户且未同步帐户,则每当修改联系人时都会重新生成LOOKUP_KEY
。
考虑到这一点,如果设备已同步,您将始终拥有唯一的 LOOKUP_KEY
。 LOOKUP_KEY
依赖于 Google Cloud,这可能与 Apple 使用的解决方案相同。
Android 设备不太可能没有 Google 帐户,因为大多数 Android 用户都依赖 Google 服务。
恐怕这是拥有唯一标识符的最佳方法,但是,如果您愿意,您可以将用户电话号码与其他联系方式结合起来,但不能保证这种方法有效,因为联系人可能会改变.如果您的用户已注册并且您将获得他们的信息,那么您可以在后端检查哪些哈希值符合您的期望,然后根据您自己的同步工作。
如果你想玩玩,我已经创建了一个 sample app 实现,你可以在其中查看联系人并找到查找键以及使用查找键检索联系人。
我还建议你看看SyncAdapter。
【讨论】:
感谢您的回答,但这不是我要找的。您的答案是在更改后获得正确的 contactId 的正确方法。但我的问题是当我使用多个 Android 设备时(或切换到新设备时)。我希望用户能够在不破坏联系人部分的应用功能的情况下切换设备。 @lior_13 如果安卓设备与谷歌账户同步,那么当您切换设备并重新同步时,您将能够跨设备搜索具有相同LOOKUP_KEY的联系人。所以只要帐号和设备同步即可。 好的,我明白你的意思。那么如果同步关闭,或者新设备还没有和账号同步,联系人信息发生了变化,那么新设备上的LOOKUP_KEY会不会链接到正确的联系人呢?如果是这样,我该怎么做才能 100% 确定我说的是同一个联系人? 是的,LOOKUP_KEY
保证会为每个联系人生成,但是如果帐户未同步,那么只要联系人被修改,LOOKUP_KEY
就会更改。考虑到这一点,如果设备已同步,您将始终拥有唯一的 LOOKUP_KEY
。 LOOKUP_KEY
依赖于 Google Cloud,这可能与 Apple 使用的解决方案相同。 Android 不太可能没有 google 帐户并且不会被同步。我已经用更多信息更新了答案。以上是关于获取 Android 手机联系人的跨设备唯一 ID的主要内容,如果未能解决你的问题,请参考以下文章