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

如何通过API替换来电号码为联系人名称?ConnectionService未生效求助

解决来电显示名称替换及ConnectionService未被调用的问题

方案一:直接用CallScreeningService改显示名(API 29+推荐)

之前你可能没注意到,Android 10(API 29)及以上的CallScreeningService其实支持直接修改来电的显示名称,根本不用折腾ConnectionService。在你的MyCallScreeningService的onScreenCall方法里,拿到API返回的真实名称后,用Response.Builder设置就行:

override fun onScreenCall(callDetails: CallDetails) {
    // 这里替换成你从API拿到的真实名称
    val realName = "某某公司"
    
    val response = CallScreeningService.Response.Builder()
        .setCallerDisplayName(realName, CallScreeningService.Response.DISPLAY_NAME_SOURCE_CUSTOM)
        .setAllowCall(true) // 允许接通电话
        .build()
    
    respondToCall(callDetails, response)
}

这么写之后,来电通知和通话界面的号码都会被替换成你设置的名称,一步到位。

方案二:修复ConnectionService没被调用的问题(兼容旧版本)

如果非要用ConnectionService(比如要兼容API 29以下),那你的代码漏了几个关键步骤:

1. 动态申请MANAGE_OWN_CALLS权限

这个权限是危险权限,只在Manifest里加没用,得在运行时弹框申请:

private fun checkAndRequestPermissions() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.MANAGE_OWN_CALLS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.MANAGE_OWN_CALLS), 1001)
    } else {
        registerTelecomManager()
    }
}

// 处理权限申请结果
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == 1001 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        registerTelecomManager()
    }
}

必须等用户授权后再调用registerTelecomManager,不然注册会失败。

2. 让用户把你的应用设为默认通话账户

注册完PhoneAccount后,系统不会自动用它处理来电,得引导用户选择:

private fun letUserSelectAccount(phoneAccountHandle: PhoneAccountHandle) {
    val intent = Intent(TelecomManager.ACTION_CHANGE_DEFAULT_PHONE_ACCOUNT)
    intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle)
    startActivity(intent)
}

在registerTelecomManager里注册完PhoneAccount后,直接调用这个方法跳转到设置页面让用户选你的账户。

3. 给ConnectionService加核心方法实现

你的MyConnectionService得重写关键方法,系统才会调用它,比如处理来电的onCreateIncomingConnection:

class MyConnectionService : ConnectionService() {
    override fun onCreateIncomingConnection(connectionManagerPhoneAccount: PhoneAccountHandle, request: ConnectionRequest): Connection? {
        val connection = object : Connection() {
            override fun onShowIncomingCallUi() {
                super.onShowIncomingCallUi()
                // 设置真实名称
                setCallerDisplayName("从API获取的名称", Connection.DISPLAY_NAME_SOURCE_CUSTOM)
            }
        }
        connection.setConnectionProperties(Connection.PROPERTY_INCOMING)
        return connection
    }
}

没这些方法,系统根本不知道怎么触发你的服务。

4. 调整PhoneAccount的Capabilities

你用的CAPABILITY_SELF_MANAGED是给VoIP应用用的,如果是处理原生蜂窝来电,得改Capabilities:

val phoneAccount = PhoneAccount.builder(phoneAccountHandle, "Phone label")
    .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER or PhoneAccount.CAPABILITY_INCOMING_CALLS)
    .build()

这样更贴合原生来电的处理场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 13:03:32