关于messager基于aidl的封装通信方式,网上有很多简单的字符串应答的测试代码。
但是对于跨应用、进程的时候,bundle传递序列化数据的时候会出现各种各样的问题。
第一个问题:对于同一应用,传递序列号对象pacelable的时候。
异常信息:
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
01-26 16:40:47.510 25379-25379/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.remote, PID: 25379
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.test.servicetest.aidl.UserInfo
at android.os.Parcel.readParcelableCreator(Parcel.java:2295)
at android.os.Parcel.readParcelable(Parcel.java:2245)
at android.os.Parcel.readValue(Parcel.java:2152)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2485)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.BaseBundle.getString(BaseBundle.java:918)
at com.test.servicetest.service.MessgeService$MessageHandler.handleMessage(MessgeService.java:46)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5667)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:962)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
解决方案:
百度了以后,在service端,onhandle方法中,写入以下信息,即可解决上面的问题。
Bundle bundle = msg.getData();
bundle.setClassLoader(getClass().getClassLoader());
运行日志:
修改后的打印log信息如下所示:能正常接收应答信息
MessageActivity: thanks ,I receive your messageUserInfo{name='test one', info='12'}
第二个问题 不同应用跨进程通信,传递序列化对象parcelable
错误信息:
service端报错信息如下
Caused by: java.lang.ClassNotFoundException: Didn't find class "aidltest.BookTest" on path: DexPathList[[zip file "/data/app/com.test.servicetest-1/base.apk", zip file "/data/app/com.test.servicetest-1/split_lib_dependencies_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_0_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_1_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_2_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_3_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_4_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_5_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_6_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_7_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_8_apk.apk", zip file "/data/app/com.test.servicetest-1/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]]
解决方案:
很明显两个应用传递的序列号对象的包名不一致,将两个应用传递的可序列号对象的包名修改为一样,即可解决上述问题
运行日志:
client端运行日志如下所示:
MessageActivity: thanks ,I receive your messageBook{bookName='android 开发艺术探索', bookPrice='59'}
问题解决了。
总结
关于跨应用和进程通讯,传递可序列化数据对象,注意以下两点:
1、在service端继承handle对象的自定义类的handleMessage(Message msg)方法中,设置类加载方法。
具体原因:android有两种classLoader:FrameWork和APK,FrameWork加载android的class,而apk加载用户自定义的类,apk继承自FrameWork,故都可以加载,在刚启动时,默认启用APK classloader。当系统空间内存不足的时候,应用会被系统回收再此启动,默认的会变为framework classloader,所以会报错。
2、确保传递可序列化数据的包名保持一致
3、messager跨进程通讯不支持 msg.object,已实践过,确实无反应。
支持的数据类型,what arg1 arg2 bundle支持的所有类型。
代码下载:源码下载地址