Android 联系人高分辨率显示照片未显示

Android contacts High-Res DisplayPhoto not showing up

我正在使用开发指南中的方法将高分辨率显示照片保存到 Android 联系人中:https://developer.android.com/reference/kotlin/android/provider/ContactsContract.RawContacts.DisplayPhoto

保存联系人后 table 看起来像这样:

------------------------------------------------------------------------------------------------------------------------------------------------------------------
| *** Contacts table ***                                                                                                                                         |
------------------------------------------------------------------------------------------------------------------------------------------------------------------
| _id | raw_contact_id | display_name | photo_id | file_id |                  photo_thumb_uri                  |                    photo_uri                    |
------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 661 |    661         | ContactName  |   6125   |    26   | content://com.android.contacts/contacts/661/photo | content://com.android.contacts/display_photo/26 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------

PhotoUri 是正确的,我确实可以使用该 URI 加载高分辨率照片。

但是,片刻之后,联系人同步服务启动了:

2019-08-30 15:17:42.991 14029-19208/? W/FSA2_ContactsSyncAdapter: @onPerformSync Sync started
2019-08-30 15:17:43.056 14029-19208/? W/ChimeraUtils: Non Chimera context
2019-08-30 15:17:43.056 14029-19208/? W/ChimeraUtils: Non Chimera context

2019-08-30 15:17:43.721 14029-19208/? I/FSA2_SyncState: @readSyncState: # aohd@ea156530

2019-08-30 15:17:44.133 14029-19208/? I/FSA2_SyncState: @readSyncState: # aohd@4c3cbbea

2019-08-30 15:17:44.335 14029-19208/? E/PhotoUrlUtil: Photo cell is empty.

2019-08-30 15:17:45.242 14029-19208/? I/FSA2_SyncUpPhotoCursor: Start to upload photo for contact 74ae94138cec7df6
2019-08-30 15:17:45.248 14029-19208/? E/PhotoUrlUtil: Photo cell is empty.
2019-08-30 15:17:45.248 14029-19208/? E/PhotoUrlUtil: Photo cell is empty.

2019-08-30 15:17:47.016 14029-19208/? W/FSA2_ContactsSyncAdapter: @onPerformSync Sync finished successfully

同步后通讯录table不正确,没有参考高分辨率照片,只有缩略图(低分辨率)照片。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------
| *** Contacts table ***                                                                                                                                           |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
| _id | raw_contact_id | display_name | photo_id | file_id |                  photo_thumb_uri                  |                    photo_uri                      |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 661 |    661         | ContactName  |   6125   |   null  | content://com.android.contacts/contacts/661/photo | content://com.android.contacts/contacts/661/photo |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------

我无法再使用来自联系人 table 的 URI 读取高分辨率数据。我正在使用以下方法阅读:

//true is for high-res photos
ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri, true)

同时,"Google Contacts" 应用程序能够加载高分辨率联系人照片。当我启动 Google 联系人应用程序时,稍后会在联系人详细信息视图中显示高分辨率照片。在 Google 应用程序中打开联系人后,我可以再次在联系人 tables.

中看到正确的条目

据我了解,在 Google 应用程序中显示联系人是在 QuickContactActivity 中实现的:

https://android.googlesource.com/platform/packages/apps/Contacts/+/refs/heads/master/src/com/android/contacts/quickcontact/QuickContactActivity.java#1120

我想了解保存(或加载)联系人高分辨率照片的正确方法是什么。我得到一个高级描述就足够了。我调查了 Google 联系人应用程序源代码,但我找不到任何简单的线索是他们是如何完成的。提供基于 Google 应用程序的简单算法食谱也算作解决方案。

我正在 Android 模拟器上测试应用程序,API 级别 28,最低。 21 级。

附加信息: 在使用 Google 联系人应用程序保存联系人照片时,我可以观察到相同的过程(如上所述)。所以看起来解析高分辨率照片信息是在照片读取期间完成的 - 这不是保存的问题。

好的,我终于找到了正确的解决方案。基本上,在查看高分辨率照片之前,您应该在同步适配器服务中触发联系人照片的同步。同步完成后,您可以检索高分辨率照片,并可以将其设置到 UI。在同步之前,通常只能使用缩略图质量的照片。

现在调度意图开始高分辨率照片同步的功能(Kotlin):

fun dispatchSyncHighResPhotoIntent(context: Context, rawContactId: Long) {
    val uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId)
    val intent = Intent()
    intent.setDataAndType(uri, ContactsContract.RawContacts.CONTENT_ITEM_TYPE)
    intent.component = ComponentName(
        "com.google.android.syncadapters.contacts",
        "com.google.android.syncadapters.contacts.SyncHighResPhotoIntentService"
    )
    intent.action = "com.google.android.syncadapters.contacts.SYNC_HIGH_RES_PHOTO"
    context.startService(intent)
}

在发送 Intent 之前,您可以设置观察者,它将在同步完成后更新您的 UI。您可以在下面找到在这种情况下有用的方法。搜索相应的文档以获取更多详细信息。


//For registering observer...
//uri - should be the same uri as uri calculated in dispatchSyncHighResPhotoIntent() function
//true - if should notify for descendants
//observer - your implementation of ContentObserver, which e.g. will update UI

context.contentResolver.registerContentObserver(uri, true, observer)


//For unregistering observer...
context.contentResolver.unregisterContentObserver(observer)

同步完成后,读取联系人的高分辨率照片应该像在文档中那样完成,或者例如通过将 Glide 与添加到数据 table.

中的 URI 一起使用
//Reading contact high-res photo as per Android documentation; true is for high-res photos
ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri, true)