跨应用发送带枚举的Broadcast触发ClassNotFoundException问题求助
解决跨应用广播传递枚举的ClassNotFoundException问题
看起来你踩了跨进程/跨应用传递Serializable对象的典型坑——接收端找不到发送端的枚举类定义,导致反序列化失败。咱们一步步拆解问题和解决方案:
问题根源
你的KeyState是MainActivity的内部静态枚举,全限定类名是com.rhr.wjc.demo.MainActivity$KeyState。当你把这个枚举对象通过putExtra放入Intent发送广播时,系统会把它序列化;而接收应用com.wjc.wecarnews的类加载器根本找不到这个类,反序列化时自然抛出ClassNotFoundException。
可行解决方案
方案1:将枚举抽为公共独立类(推荐)
把KeyState从MainActivity中抽出来,做成一个独立的公共枚举类,放在两个应用都能访问到的包路径下(比如com.coagent.common),然后两个应用都依赖这个类:
发送端的枚举定义修改为:
package com.coagent.common; public enum KeyState { NONE, DOWN, UP }
发送广播代码不变:
Intent intent = new Intent("com.coagent.intent.action.test"); intent.putExtra("Key_state", KeyState.NONE); MainActivity.this.sendBroadcast(intent);
接收端直接强转(无需再用Serializable中转):
String EXTRA_KEY_STATE="Key_state"; KeyState keyState = (KeyState) intent.getSerializableExtra(EXTRA_KEY_STATE); String ks = keyState.toString(); LogUtils.i(TAG, "Wjc handerChangAnAction: ks=" + ks); if (null != ks && !ks.equals("NONE")) { return; }
方案2:传递枚举的字符串/序号(无需公共类)
如果不想引入公共依赖,最稳妥的方式是传递枚举的名称字符串或者序号值,接收端直接解析:
方式A:传递枚举名称
发送端修改:
Intent intent = new Intent("com.coagent.intent.action.test"); // 传递枚举的名称字符串 intent.putExtra("Key_state", KeyState.NONE.name()); MainActivity.this.sendBroadcast(intent);
接收端处理:
String EXTRA_KEY_STATE="Key_state"; String ks = intent.getStringExtra(EXTRA_KEY_STATE); LogUtils.i(TAG, "Wjc handerChangAnAction: ks=" + ks); if (null != ks && !ks.equals("NONE")) { return; }
方式B:传递枚举序号
发送端修改:
Intent intent = new Intent("com.coagent.intent.action.test"); // 传递枚举的序号(注意:如果后续枚举顺序变动,会导致解析错误) intent.putExtra("Key_state", KeyState.NONE.ordinal()); MainActivity.this.sendBroadcast(intent);
接收端处理(建议接收端也定义相同的枚举,保证顺序一致):
// 接收端本地定义相同的枚举 public enum KeyState { NONE, DOWN, UP } // 解析逻辑 String EXTRA_KEY_STATE="Key_state"; int ordinal = intent.getIntExtra(EXTRA_KEY_STATE, -1); if (ordinal == -1) { // 处理异常情况 return; } KeyState keyState = KeyState.values()[ordinal]; String ks = keyState.toString(); LogUtils.i(TAG, "Wjc handerChangAnAction: ks=" + ks); if (null != ks && !ks.equals("NONE")) { return; }
方案3:实现Parcelable(不推荐)
让枚举实现Parcelable接口,但本质还是需要两个应用的枚举类定义完全一致,和方案1的依赖要求一样,而且代码更繁琐,没必要多此一举。
总结
跨应用传递数据时,尽量避免直接传递自定义Serializable/Parcelable对象(除非是公共依赖的类),优先使用基本数据类型、字符串这些通用类型,能避免很多类加载相关的问题。
内容的提问来源于stack exchange,提问作者Alice
相关产品推荐
相关产品推荐

