【问题标题】:Persistant contact id永久联系人 ID
【发布时间】:2019-02-25 17:25:33
【问题描述】:

我知道在某些手机上,即使重新启动,联系人 ID 也会发生变化,但我无法在自己的手机上重现这一点。但我可以重现以下案例,并想知道这个案例是否至少可以解决:

  • 安装whatsapp - 它会将它的联系人添加到ContentProvider
  • ContactProvider 读取联系人 => 我得到数据集 1
  • 删除 whatsapp,重新安装 - 它会将其联系人再次添加到 ContentProvider
  • ContentProvider 读取联系人 => 我得到数据集 2

结果:

在数据集 1 和数据集 2 之间,我没有看到任何一致的数据。

例如:

ContactsContract.Data.CONTACT_ID => 更改,例如从598679 ContactsContract.Data.LOOKUP_KEY => 也会发生变化,例如3514i2b4948808eec75c9.3789r593-2D374B39.2797r594-2D374B393514i2b4948808eec75c9.2797r603-2D374B39.3789r670-2D374B39 * 当然,一些raw ids 保持不变,但就我所见,完整联系人的通用ID 没有保持不变

我想要什么

我需要一个联系人标识符,我可以在我的应用程序的数据库中保留该标识符,并且在进行上述更改后也可以使用该标识符。 我需要一个联系人的标识符(不是原始联系人),原始联系人当然可能会在联系人的生命周期内发生变化(就像我在上面描述的示例中一样)...

有什么办法可以解决这个问题吗?

代码

为了完整起见,下面是我从ContentProvider查询数据的方法,至少是光标:

 private fun getCursor(offset: Int?, count: Int?): Cursor? {
    val selection = arrayOf(
            ContactsContract.Data.RAW_CONTACT_ID,
            ContactsContract.Data.CONTACT_ID,
            ContactsContract.Data.LOOKUP_KEY,
            ContactsContract.Data.PHOTO_ID,
            ContactsContract.Data.DISPLAY_NAME,
            ContactsContract.Data.ACCOUNT_TYPE_AND_DATA_SET,
            ContactsContract.CommonDataKinds.Email.DATA,
            ContactsContract.CommonDataKinds.Phone.NUMBER,
            ContactsContract.CommonDataKinds.Phone.TYPE,
            ContactsContract.CommonDataKinds.Phone.LABEL,
            ContactsContract.Contacts.Data.MIMETYPE,
            ContactsContract.RawContacts.ACCOUNT_NAME,
            ContactsContract.CommonDataKinds.Phone.IS_PRIMARY,
            ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP,
            ContactsContract.RawContacts.SOURCE_ID
    )

    return AppProvider.get().context.contentResolver.query(
            ContactsContract.Data.CONTENT_URI,
            selection, null, null,
            ContactsContract.Data.CONTACT_ID + " ASC" + if (offset != null && count != null) " limit $count offset $offset" else "")
}

【问题讨论】:

    标签: android android-contacts contactscontract


    【解决方案1】:

    LOOKUP_KEY 是你的朋友。

    LOOKUP_KEY

    一个不透明的值,其中包含有关如何查找 如果其行 ID 由于同步或聚合而发生更改,请联系。

    所以它本身并不是一个稳定的 ID,但它可以帮助 ContactsContract DB 找出新的contactID,以防它发生变化。

    您应该使用 一对 <CONTACT_ID, LOOKUP_KEY> 来跟踪联系人。 在正常使用中,使用CONTACT_ID 值,但如果您的代码提示CONTACT_ID 已更改(缺少或意外的联系人姓名),您可以使用LOOKUP_KEY查找 新的联系人 ID。

    您可以使用Contacts.getLookupUri(long, String) 获取一个URI,无论其CONTACT_IDLOOKUP_KEY 的实际值是什么,您都可以使用它来快速查找联系人。

    【讨论】:

    • 但是,如果您重命名联系人或重新同步在线联系人提供商(甚至更多),此密钥有时也可能会损坏...对我来说,根据我的测试,它看起来是目前最好的解决方案是使用主要联系人的原始ID,这个在我的测试用例中是稳定的。使用此 ID,我可以查询当前的联系人 ID,并使用此联系人 ID,我可以查询该联系人的所有数据。您如何看待这个解决方案?
    • 这不好,“主要”我假设您在大多数情况下是指谷歌原始联系人,这些也可以更改(有时在“谷歌联系人同步屏幕”下的“同步失败”消息帐户”> google,这将触发所有 google 联系人的重新同步,更改其原始 ID)。如果您更改联系人的姓名,它可以给您的应用程序一个“提示”联系人 ID 可能是错误的,因此您将使用 getLookupUri 方法查找新的联系人 ID 只是为了获得相同的 ID,所以没关系
    • 好的,谢谢。您写了“缺少或意外的联系人姓名”——意外的姓名真的会出现吗?在我的测试用例中,旧的联系人 id 总是被删除并创建一个新的更高的联系人......在这种情况下,如果无法找到保存的联系人 id,我可以使用旧的查找键来查找新的联系人 id。
    • 这种情况比较少见,但可能会发生,例如在 root 设备上,用户可以在安装新 ROM 后使用 Titanium Backup 来恢复您的应用程序,在这种情况下,所有联系人都有相同的联系范围 - ids(不高于旧)但完全不同,还有其他类似的例子
    • 那是用户当时的意图并且是可以接受的。所以一般来说,以下情况是正确的:1)一个联系人 ID 将始终链接到同一个联系人(罕见的恢复情况、清理或类似情况除外) 2)在这种情况下,我们可以依靠我们可以使用联系人 ID 来查找联系人,如果我们没有找到联系人,我们可以使用 lookup_key 找到新的联系人 => 如果您直接使用 Contacts.getLookupUri(long, String) 获取联系人,则完成一些操作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多