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

如何在使用ConnectionService的addNewIncomingCall时显示自定义UI?

如何通过ConnectionService实现自定义来电UI?

我正在实现ConnectionService,调用addNewIncomingCall时会弹出系统默认的来电接听/拒接UI。

调用来电的代码示例:

var handle = account.accountHandle
val extras = Bundle()
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, handle)
val manager = getSystemService(Context.TELECOM_SERVICE) as TelecomManager

manager.addNewIncomingCall(handle, extras)

注册账号的代码:

fun registerConnectionService() {
    val manager = getSystemService(Context.TELECOM_SERVICE) as TelecomManager
    val connectionServiceId = getConnectionServiceId()
    val componentName =
        ComponentName(applicationContext, PhoneConnectionService::class.java)
    val phoneAccountHandle = PhoneAccountHandle(componentName, connectionServiceId)
    val builder = PhoneAccount.builder(
        phoneAccountHandle,
        this.resources.getText(R.string.app_name)
    )
    val uri = Uri.fromParts("tel", "123456789", null)
    builder.setSubscriptionAddress(uri)
    builder.setAddress(uri)
    builder.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)

    builder.setShortDescription("Short description")
    phoneAccount = builder.build()
    manager.registerPhoneAccount(phoneAccount)
}

我知道需要设置PhoneAccount.CAPABILITY_SELF_MANAGED来启用自定义UI:

builder.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED)

接收来电的ConnectionService代码:

@Override
public Connection onCreateIncomingConnection(PhoneAccountHandle connectionManagerPhoneAccount, ConnectionRequest request) {
    final CallConnection connection = new CallConnection(this);

    Bundle extras = new Bundle();

    connection.setAddress(request.getAddress(), PRESENTATION_ALLOWED);
    connection.setVideoState(VideoProfile.STATE_AUDIO_ONLY);
    connection.setExtras(extras);
    connection.setConnectionCapabilities(Connection.CAPABILITY_SUPPORT_DEFLECT);
    connection.setRingbackRequested(true);
    connection.setRinging();

    return connection;
}

但继承自Connection的CallConnection类中的onShowIncomingCallUi方法始终没有被调用,请问该如何解决?


解决方案

要让onShowIncomingCallUi触发并正常使用自定义来电UI,需逐一检查并完成以下配置:

  1. 修正PhoneAccount的能力配置
    不要直接替换掉CAPABILITY_CALL_PROVIDER,需同时保留两种能力(如果你的应用仍需作为通话提供商):

    builder.setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED or PhoneAccount.CAPABILITY_CALL_PROVIDER)
    

    CAPABILITY_SELF_MANAGED的核心作用是告知系统:该应用将自行处理来电UI,无需弹出系统默认界面。

  2. 完善ConnectionService的Manifest声明
    在AndroidManifest.xml中注册服务时,必须绑定指定权限并添加正确的Intent Filter:

    <service
        android:name=".PhoneConnectionService"
        android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
        <intent-filter>
            <action android:name="android.telecom.ConnectionService" />
        </intent-filter>
    </service>
    
  3. 确保CallConnection正确重写方法
    检查你的CallConnection类是否正确实现onShowIncomingCallUi,并在方法内启动自定义来电UI的Activity:

    public class CallConnection extends Connection {
        public CallConnection(Context context) {
            super(context);
        }
    
        @Override
        public void onShowIncomingCallUi() {
            // 启动自定义来电UI页面
            Intent intent = new Intent(getContext(), CustomIncomingCallActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            getContext().startActivity(intent);
        }
    }
    
  4. 检查必要权限
    根据系统版本,确保应用已获取对应权限:

    • Android 10及以上:READ_PHONE_STATE、ANSWER_PHONE_CALLS
    • Android 13及以上:额外需要POST_NOTIFICATIONS(来电通知是触发UI的前提)
      部分定制ROM可能需要手动在系统设置中允许应用作为默认通话应用。
  5. 优化来电调用时的参数
    调用addNewIncomingCall时,避免传递强制使用系统UI的参数,可补充自定义参数供后续UI使用:

    val extras = Bundle().apply {
        putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, handle)
        // 可添加自定义键值对,传递来电相关信息
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:05:12