You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取联系人照片Bitmap?转换content URI时遇‘unimplemented’错误

解决联系人照片转Bitmap的"unimplemented"错误

问题原因

你碰到的Failed to create image decoder with message 'unimplemented'错误,核心是content://com.android.contacts/display_photo/这类URI属于系统封装的联系人照片资源,不能直接用BitmapFactory.decodeStream解析。此外你的代码还有两个明显问题:

  • 同一个InputStream被连续两次调用decodeStream,第一次读取后流指针已到末尾,第二次必然返回null
  • 没有处理联系人无自定义照片时的默认头像逻辑

修复代码

替换原照片读取逻辑,使用系统提供的专用接口处理联系人照片,同时补充默认头像的加载逻辑:

private fun getContactNumbers(): ArrayList<ArrayList<String>> {
    val contactsNumberMap = ArrayList<ArrayList<String>>()
    val phoneCursor: Cursor? = context.contentResolver.query(
        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
        null,
        null,
        null,
        null
    )
    if (phoneCursor != null && phoneCursor.count > 0) {
        val numberIndex = phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
        val nameIndex = phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)
        // 改用联系人ID获取照片,比直接读取PHOTO_URI更稳定
        val contactIdIndex = phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)

        while (phoneCursor.moveToNext()) {
            val number: String = phoneCursor.getString(numberIndex)
            val name: String = phoneCursor.getString(nameIndex)
            val contactId: Long = phoneCursor.getLong(contactIdIndex)
            val objectNameNumber = ArrayList<String>()
            objectNameNumber.add(name)
            objectNameNumber.add(number)

            // 处理联系人照片
            var contactBitmap: Bitmap? = null
            val contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId)
            // 系统专用接口读取联系人照片流
            context.contentResolver.openContactPhotoInputStream(contactUri)?.use { inputStream ->
                contactBitmap = BitmapFactory.decodeStream(inputStream)
            }
            // 无自定义照片时加载默认头像
            if (contactBitmap == null) {
                contactBitmap = BitmapFactory.decodeResource(context.resources, R.drawable.ic_default_contact)
            }

            // 可根据需求将contactBitmap加入数据结构,比如objectNameNumber.add(contactBitmap)(需调整结构类型)
            println("${name}的头像处理完成")

            if (!contactsNumberMap.contains(objectNameNumber)) {
                contactsNumberMap.add(objectNameNumber)
            }
        }
        phoneCursor.close()
    }
    return contactsNumberMap
}

关键修复点

  • 专用接口解析照片:openContactPhotoInputStream是系统为联系人照片提供的适配接口,能正确解析display_photo类型的URI
  • 避免流重复读取:用use关键字自动管理流的生命周期,确保只读取一次
  • 默认头像兜底:当无自定义照片时,加载应用内的默认头像资源
  • 改用Contact ID生成URI:相比直接读取PHOTO_URI,通过Contact ID拼接的URI格式更稳定,减少异常概率

额外注意事项

  • 必须在AndroidManifest.xml中声明权限:
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    
  • Android 6.0及以上版本需动态申请READ_CONTACTS权限

内容的提问来源于stack exchange,提问作者Avadhesh Mourya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 17:45:27