Android应用间能否通过Broadcast Receiver传递自定义对象?
很遗憾,你这个方案完全不可行,核心原因在于Android的类加载器隔离机制,下面给你拆解清楚:
为什么不行?
Android里每个应用都是独立进程,拥有专属的类加载器。哪怕你在App B里定义的CustomClass和App A里的类名、字段、方法完全一模一样,在虚拟机看来它们也是两个完全不同的类——因为类的唯一标识是「类加载器+全限定类名」,二者只要有一个不同,就会被判定为不同类型。
当App B把自己的CustomClass对象序列化后通过Intent传递,App A的BroadcastReceiver尝试用(CustomClass)intent.getSerializableExtra("msg_bean")强转时,会直接抛出ClassCastException:A的类加载器加载的CustomClass,和B序列化过来的类根本不是同一个类型。
可行的替代方案
1. 共用同一个类库(最推荐)
把CustomClass以及它依赖的相关代码,抽成一个独立的Android Library模块,然后让App A和App B都依赖这个库。这样两个App里的CustomClass本质是同一个字节码文件,虽然类加载器不同,但类的全限定名和哈希值完全一致,序列化/反序列化就能正常工作。
2. 转换成通用数据格式传递
如果不想抽类库,可以把对象转换成跨进程通用的格式:
- JSON字符串:用Gson、FastJson等库把
CustomClass对象转成JSON字符串,通过intent.putExtra("msg_bean", jsonStr)传递,在Receiver里再把字符串解析回A的CustomClass对象。 - Parcelable:不过Parcelable跨进程对类的一致性要求极高,本质和Serializable面临的问题类似,不如JSON稳妥,除非你能100%保证两边的Parcelable实现完全一致。
3. 其他跨进程通信方式
如果广播不是必须的,也可以考虑用ContentProvider、AIDL等更可靠的跨进程通信方式,但对于简单的对象传递,前两种方案足够轻便。
错误场景示例
假设App A的CustomClass包名是com.appa.model.CustomClass,App B的是com.appb.model.CustomClass,哪怕代码完全一样,当B传递对象后,A的Receiver尝试强转时,虚拟机就会判定:
你给我的是
com.appb.model.CustomClass类型,但我要的是com.appa.model.CustomClass,类型不匹配!
哪怕包名完全相同,只要是两个App各自编译的类,类加载器不同,依然会触发类型转换异常。
内容的提问来源于stack exchange,提问作者Lew Wei Hao

