如何通过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
相关产品推荐
相关产品推荐

