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

在ConnectionService读取Bundle时出现CallInvite类未找到异常

解决ConnectionService中读取Twilio CallInvite时的ClassNotFoundException问题

问题核心

你遇到的ClassNotFoundException本质是Android系统进程与应用进程的类加载器隔离导致的:

  • ConnectionService由系统Telecom进程启动,该进程的类加载器无法访问你应用依赖的com.twilio.voice.CallInvite类(该类仅存在于你的应用进程类加载器中)。
  • Android 11/12强化了进程隔离机制,即使CallInvite实现了Parcelable接口,跨进程传递时系统进程也无法找到对应的类创建实例,甚至会出现Parcel读取时类名为null的情况。

解决方案

1. 避免直接传递CallInvite对象

不要将CallInvite直接存入TelecomManager.EXTRA_INCOMING_CALL_EXTRAS对应的Bundle中,改为提取CallInvite的关键可序列化字段(如callSid、from、to、token等基础数据类型或字符串)存入Bundle。

示例代码(Kotlin):

// FCM消息处理时,解析CallInvite并提取参数
val callInvite = CallInvite.fromIntent(intent)
val extrasBundle = Bundle().apply {
    putString("call_sid", callInvite.callSid)
    putString("from_number", callInvite.from)
    putString("to_number", callInvite.to)
    putString("voice_token", callInvite.token)
    putInt("notification_id", notificationId)
}

// 调用TelecomManager发起来电请求
val telecomManager = getSystemService(Context.TELECOM_SERVICE) as TelecomManager
val callIntent = Intent(TelecomManager.ACTION_SHOW_INCOMING_CALL).apply {
    putExtra(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extrasBundle)
    // 补充其他必要参数
}
startForegroundService(callIntent)

2. 在ConnectionService中重构通话信息

在onCreateIncomingConnection方法中,从Bundle读取提取的字段,而非尝试反序列化CallInvite:

override fun onCreateIncomingConnection(
    connectionManagerPhoneAccount: PhoneAccountHandle?,
    request: ConnectionRequest?
): Connection? {
    val extras = request?.extras ?: return null
    val callSid = extras.getString("call_sid")
    val fromNumber = extras.getString("from_number")
    
    // 创建Connection并设置参数
    val connection = object : Connection() {
        override fun onAnswer() {
            // 通过callSid等参数,从应用进程获取完整的CallInvite实例并处理接听逻辑
            // 可通过LocalBroadcast、Messenger等方式跨进程通信
        }
    }
    connection.setAddress(Uri.parse("tel:$fromNumber"), TelecomManager.PRESENTATION_ALLOWED)
    // 配置其他Connection参数
    return connection
}

3. 跨进程获取完整CallInvite实例

如果业务需要完整的CallInvite对象,可通过以下方式在ConnectionService中从应用进程获取:

  • 使用LocalBroadcastManager发送包含callSid的广播,应用进程接收后返回完整的CallInvite(需确保应用进程存活)。
  • 通过Messenger建立跨进程通信通道,应用进程作为服务端,ConnectionService作为客户端请求CallInvite数据。

关键注意事项

  • 跨进程传递的数据必须是Android系统类加载器可识别的类型(如基本类型、String、ArrayList、Bundle等),禁止传递第三方库自定义的Parcelable/Serializable对象。
  • 确保在AndroidManifest.xml中正确声明ConnectionService并添加权限:
<service
    android:name=".MyConnectionService"
    android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE">
    <intent-filter>
        <action android:name="android.telecom.ConnectionService" />
    </intent-filter>
</service>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:10:32