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

使用Authenticator Service给联系人添加自定义MIME-Type时部分联系人重复

我编写了Sync Adapter和Authenticator Service来添加自定义MIME-Type,用于实现应用内通话功能:用户在联系人中点击对应条目即可打开本应用,效果类似WhatsApp、Telegram的实现逻辑。

目前Authenticator Service和同步执行逻辑运行正常,仅在部分设备上出现联系人重复问题:如*Pixel 3a(Android 11)上部分联系人会生成重复条目,重复联系人仅保留姓名和本应用的呼叫按钮,无其他信息;而POCO F1(Android 10)*等设备完全不会出现重复问题。

重复并非随机现象:卸载应用重装后再执行同步操作,重复的始终是同一批联系人。

问题截图如下:
联系人应用中的重复联系人

以下是我编辑联系人的实现代码(参考了Stack Overflow方案):

fun addContact(context: Context, user: User) {
    if (user.phoneNo.isNullOrEmpty()) {
        Log.e("IS EMPTY", "phone = ${user.phoneNo} email : ${user.email}")
        return
    }
    val resolver: ContentResolver = context.contentResolver
    val ops = ArrayList<ContentProviderOperation>()
    ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI))
            .withValue(RawContacts.ACCOUNT_NAME, context.applicationInfo.loadLabel(context.packageManager).toString())
            .withValue(RawContacts.ACCOUNT_TYPE, AccountConstants.ACCOUNT_TYPE)
            .build())
    ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(ContactsContract.Settings.CONTENT_URI))
            .withValue(RawContacts.ACCOUNT_NAME, context.applicationInfo.loadLabel(context.packageManager).toString())
            .withValue(RawContacts.ACCOUNT_TYPE, AccountConstants.ACCOUNT_TYPE)
            .withValue(ContactsContract.Settings.UNGROUPED_VISIBLE, 1)
            .build())
    ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI))
            .withValueBackReference(Data.RAW_CONTACT_ID, 0)
            .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
            .withValue(StructuredName.GIVEN_NAME, user.name)
            .build())

    if (!user.phoneNo.isNullOrEmpty())
        ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI))
                .withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, MIMETYPE_CALL)
                .withValue(Data.DATA1, user.phoneNo)
                .withValue(Data.DATA2, "Call")
                .withValue(Data.DATA3, "Make a Call")
                .build())
//Disregard Message and Email MIME Type
    if (!user.phoneNo.isNullOrEmpty())
        ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI))
                .withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, MIMETYPE_MESSAGE)
                .withValue(Data.DATA1, user.phoneNo)
                .withValue(Data.DATA2, "Message")
                .withValue(Data.DATA3, "Send a Message")
                .build())

    if (!user.email.isNullOrEmpty())
        ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI))
                .withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, MIMETYPE_EMAIL)
                .withValue(Data.DATA1, user.email)
                .withValue(Data.DATA2, "Email")
                .withValue(Data.DATA3, "Send an Email")
                .build())
    try {
        Log.d("voice", "Add Phone Number: " + user.phoneNo
                + " id = " + user.id)
        resolver.applyBatch(ContactsContract.AUTHORITY, ops)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

private fun addCallerIsSyncAdapterParameter(uri: Uri): Uri {
    return uri.buildUpon()
            .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
            .build()
}

另外我在搭载Android 12的Pixel 3a模拟器上使用相同数据测试,未复现该重复问题。我暂未定位到代码中的问题点,恳请各位帮忙排查,任何帮助都十分感谢。


内容的提问来源于stack exchange,提问作者Sahdeep Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 21:45:03