在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
相关产品推荐
相关产品推荐

