【问题标题】:Should I rely on SOURCE_ID when reading Android Contacts?阅读 Android 通讯录时我应该依赖 SOURCE_ID 吗?
【发布时间】:2017-02-01 20:04:23
【问题描述】:

我正在创建一个 android 联系人应用程序,因此我会定期读取用户的联系人并将它们存储在我的应用程序中。为此,我需要依赖某种ID,以便我知道我应该在我的应用程序中更新(或添加/删除)哪个联系人,并且Contacts Provider 提供了其中的几个:

  • CONTACT_ID 是聚合的联系人 ID,
  • 每个聚合联系人由一个或多个原始联系人组成,每个联系人都有自己的RAW_CONTACT_ID
  • 最重要的是,每个原始联系人都有一个SOURCE_ID,它应该是服务器ID,即此联系人在此帐户服务器中的ID。

我选择依赖SOURCE_ID,因为这听起来是最稳定的。例如。当用户在他们的设备中删除并重新添加同一个帐户时,我不希望此帐户的联系人获得不同的 ID,因为我无法在我的应用中匹配它们。

然而,似乎只有 Gmail 同步适配器遵守了下面记录的承诺。不幸的是,Exchange 同步适配器没有,SOURCE_ID 发生变化,而且它绝对不是任何服务器 ID,因为它有一个像 23:4 这样的小数字。

问题:有什么想法可以解决这个问题吗?我是否将正确的ID 用于预期用途?交换适配器是否将“永久服务器 ID”存储在其他字段中?

文档SOURCE_IDmust be unique for each account type and should be stable across syncs

  • 唯一:帐户的每个原始联系人都必须有自己的源 ID。如果您不执行此操作,则会导致联系人出现问题 应用。请注意,同一帐户类型的两个原始联系人 可能具有相同的源 ID。例如,原始联系人“Thomas Higginson”帐户 emily.dickinson@gmail.com 被允许 具有与原始联系人“Thomas Higginson”相同的源 ID 帐户 emilyd@gmail.com。
  • 稳定:源 ID 是原始联系人在线服务数据的永久部分。例如,如果用户清除联系人存储 从应用程序设置和重新同步,恢复的原始联系人应该 具有与以前相同的源 ID。如果你不强制执行, 快捷方式将停止工作。

【问题讨论】:

    标签: android android-contacts android-syncadapter


    【解决方案1】:

    LOOKUP_KEY 就是你要找的东西。

    LOOKUP_KEY

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

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

    或者您可以使用 Contacts.getLookupUri() 获取一个 URI,无论其 CONTACT_ID 或 LOOKUP_KEY 实际值是什么,您都可以始终使用它来快速查找联系人。

    【讨论】:

    • 感谢您的回答,但是删除,重新添加帐户的情况如何?我猜LOOKUP_KEYs 会改变,不是吗?
    • LOOKUP_KEY 并不是一个稳定的 ID,所以,是的,它会改变,但您可以总是使用 Contacts.getLookupUri(id, key) 来获取uri 将指向同一个联系人(无论它的新 ID 是什么)。查找键包含hints 到系统如何找到该联系人
    • 不幸的是,LOOKUP_KEY 并没有什么魔力。它也取决于sourceId。我做了一个测试,其中contactAsourceId2:16lookupKey = 1016i2%3A16(注意2%3A162:16 url 编码的)。然后删除并重新添加该帐户。 contactASourceId 现在是2:12lookupKey = 1016i2%3A12,最糟糕的是,一些随机的contactBlookupKey = 1016i2%3A16。这就是为什么当我用lookupKey = 1016i2%3A16 调用Contacts.getLookupUri(id, key) 并使用该Uri 检索联系人时,我得到的是contactB 而不是contactA
    • 让我大吃一惊的是,当我尝试创建contactA 的快捷方式时,从那时起,sourceId 从未更改过,无论我删除并重新添加了多少次相同的帐户(交换),即使我删除了快捷方式。
    • 这真的很奇怪...通过创建快捷方式,您的意思是在主屏幕上添加一个快捷方式图标以打开该联系人的个人资料?
    【解决方案2】:

    首先,将 Id 存储在您的应用程序中并希望 Id 不会随时间变化并保持一致并不是一个好主意。您对“SOURCE_ID”列的看法是正确的,与其他两个相比,它更加一致(CONTACT_ID 是最脆弱的,而“RAW_CONTACT_ID”至少会持续存在直到用户注销帐户并再次登录)。

    我们有一个可与联系人同步的帐户,过去我们将 unique id 保留在“raw_contacts”表 (SYNC1 - SYNC10) 的一个通用列中。因此,尽管 Google 建议帐户提供者以某种方式使用数据库列,但这完全取决于提供者。

    要遵循的一般规则是,永远不要将这些 id 用于长期持久性,如果您这样做,期望它们会改变。此外,由于您正在制作联系人应用程序,因此您显然需要某种参考密钥。在这种情况下,不要遵循所有帐户提供者将其密钥放在同一列中的规则。它很脆,但就是这样。

    编辑 - 您应该使用 ContactsColumns.LOOKUP_KEY (以前的答案也引用了相同的内容)。根据 Google 文档 -

    LOOKUP_KEY

    在 API 级别 5 中添加 String LOOKUP_KEY 一个不透明的值,包含 如果联系人的行 ID 因以下原因而更改,则提示如何查找联系人 同步或聚合。

    常量值:“查找”

    https://developer.android.com/reference/android/provider/ContactsContract.ContactsColumns.html#LOOKUP_KEY

    如果您有使用提供的 API 的联系人 ID,则可以获取查找密钥。看这里-https://developer.android.com/reference/android/provider/ContactsContract.Contacts.html

    【讨论】:

    • 好的,所以你建议如果我依赖IDs,我应该期望它们会随着时间而改变。那么,如果不是这些 ID,我可以使用哪些更永久的参考?
    • 您的问题已被其他答案回答。您需要使用的密钥是Contacts.LOOKUP_KEY。通常,查找键是由许多组件生成的复合键。我刚刚编辑了我的答案
    猜你喜欢
    • 2021-03-08
    • 2016-01-26
    • 2012-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 1970-01-01
    • 2021-01-28
    相关资源
    最近更新 更多