Android中跨进程通信传递Parcelable对象时出现android.os.BadParcelableException: ClassNotFoundException when unmarsh

转载请注明出处:http://blog.csdn.net/bettarwang/article/details/45315091

按Google开发文档的说法,在跨进程通信时,推荐使用MessengerService而不是AIDL,所以最近在实现一个跨进程的Service时就采用了MessengerService的方法。

然后定义了这样一个类:

public class BleServiceBean implements Parcelable {

    private String name;

    private String uuid;

    public BleServiceBean()
    {

    }

    public BleServiceBean(BluetoothGattService service)
    {
        uuid=service.getUuid().toString();
        name= BleNamesResolver.resolveServiceName(uuid);
    }

    private BleServiceBean(Parcel in)
    {
        readFromParcel(in);
    }

    private void writeToParcel(Parcel out)
    {
        out.writeString(name);
        out.writeString(uuid);
    }

    @Override
    public int describeContents()
    {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out,int flags)
    {
        writeToParcel(out);
    }

    public void readFromParcel(Parcel in)
    {
        name=in.readString();
        uuid=in.readString();
    }

    public static final Parcelable.Creator<BleServiceBean>CREATOR=new
            Parcelable.Creator<BleServiceBean>(){
              @Override
              public BleServiceBean createFromParcel(Parcel source)
              {
                  return new BleServiceBean(source);
              }

              @Override
              public BleServiceBean[]newArray(int size)
              {
                  return new BleServiceBean[size];
              }

            };
}

在Service中获取到相应数据后要传递给UI,有如下代码:

 Bundle bundle=new Bundle();
                bundle.putParcelableArrayList(BleConnectUtils.BLE_SERVICE_BEAN_LIST,beanList);
                msg.setData(bundle);
                mClients.get(i).send(msg);

在Client端获取数据的代码如下:

ArrayList<BleServiceBean>beanList=bundle.getParcelableArrayList(BleConnectUtils.BLE_SERVICE_BEAN_LIST);

但是运行到此处时却出现如下错误:

FATAL EXCEPTION: main

Process: com.example.xxx.xx, PID: 1203

android.os.BadParcelableException: ClassNotFoundException when unmarshalling:

给出的出错原因如下:

Caused by: java.lang.ClassNotFoundException: Didn‘t find class "com.example.xxx.xxx.bean.BleServiceBean" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /data/cust/lib, /system/lib]]

后面才发现原来是Android有两种不同的classloaders:framework
classloader和apk classloader,其中framework classloader知道怎么加载android classes,apk classloader知道怎么加载你的代码,即可以知道你自定义的类,apk classloader继承自framework classloader,所以也知道怎么加载android classes。在应用刚启动时,默认class
loader是apk classloader,但在系统内存不足应用被系统回收会再次启动,这个默认class loader会变为framework classloader了,所以对于自己的类会报ClassNotFoundException。

如果是在要传递的JavaBean中有其中一个Field继承自Parcelable,那么有很简单的处理方法,只要把类似rect =
in.readParcelable(null);改为config = in.readParcelable(Rect.class.getClassLoader());

但是我们这里是直接传递一个List<BleServiceBean>,那要怎么办呢?

其实很简单,只需要在Client端读取Bundle中的数据之前加上如下一行代码:

bundle.setClassLoader(getClass().getClassLoader());

这样就会使用apk classloader加载。

时间: 2024-05-09 08:16:32

Android中跨进程通信传递Parcelable对象时出现android.os.BadParcelableException: ClassNotFoundException when unmarsh的相关文章

【朝花夕拾】一篇文章搞懂Android跨进程通信

前言 只要是面试中高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Android开发高级工程师必须要跨过的一道坎.如果您还对这方面的知识还做不到如数家珍,那就和我一起来攻克它吧! 本文主要包含了如下内容: 其行文脉络大致如下,希望能加深读者对这方面内容的记忆:(1)Android基于Linux系统,所以先说系统进程相关知识和Linux IPC.(2)总结Android的IPC

android Activity之间数据传递 Parcelable和Serializable接口的使用

Activity之间传数据时,为了避免麻烦,往往会将一些值封装成对象,然后将整个对象传递过去.传对象的时候有两种情况,一种是实现Parcelable接口,一种是实现Serializable接口.0.解释两种接口:1)实现Serializable接口是JavaSE本身就支持的.2)Parcelable是Android特有的功能,效率比实现Serializable接口高,像用于Intent数据传递也都支持,而且还可以用在进程间通信(IPC),除了基本类型外,只有实现了Parcelable接口的类才能

Android中跨进程通信方式之使用文件共享

一.使用Serializable序列化对象 import java.io.Serializable; public class User implements Serializable{ private static final long serialVersionUID = 1L; private String username; private String password; public String getUsername() { return username; } public v

【朝花夕拾】性能优化篇之(八)AIDL与Android跨进程通信

一.Linux进程间通信 1.进程隔离 在操作系统中,进程与进程间的内存和数据都是不共享的.两个进程就好像大海中相互独立的两个岛屿,各自生活在互相平行的两个世界中,互不干扰,各自为政.这样做的目的,是为了避免进程间相互操作数据的现象发生,从而引起各自的安全问题.为了实现进程隔离,采用了虚拟地址空间,两个进程各自的虚拟地址不同,从逻辑上来实现彼此间的隔离. 马克思主义哲学说,人是一切社会关系的总和.任何一个个体都不可能完全隔离于外界,都不可避免地与外界"互通有无".进程也一样,时不时需要

android.os.BadParcelableException: ClassNotFoundException when unmarshalling:解决办法

例如在用AlarmManager的时候 1 AlarmManager alarmMgr = (AlarmManager) mContext 2 .getSystemService(Context.ALARM_SERVICE); 3 Intent intent = new Intent(ALARM_ALERT); 4 // intent.setExtrasClassLoader(DBTask.class.getClassLoader()); 5 Bundle mBundle=new Bundle(

Chromium中跨进程文件句柄传递

实现说明 在Chromium跨进程架构下,也会有Browser/Renderer两个进程对相同文件进行操作的需求.比如Browser的某个任务依赖于Renderer端对指定文件的输出.而在POXIS下,允许不同进程间传递文件描述符(File Descriptor))的, 比如传递socket,或者普通文件,进而可以达到不需要重新打开文件,而对相同文件读写的效果(并不是分享文件句柄).Chromium对这个特性做了封装,也包括了Windows下的实现(也包括了Windows下的实现).涉及的基本结

Android笔记之Intent传递自定义对象

1. import java.util.List; import android.os.Parcel; import android.os.Parcelable; /** * 1)writeToParcel 方法.该方法将类的数据写入外部提供的Parcel中. * 2)describeContents方法.直接返回0就可以. * 3)静态的Parcelable.Creator<T>接口,本接口有两个方法: * createFromParcel(Parcel in) 实现从in中创建出类的实例的

android 跨进程通信

转自:http://www.androidsdn.com/article/show/137 由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些.在android SDK中提供了4种用于跨进程通讯的方式.这4种方式正好对应于android系统中4种应用程序组件:Activity.Content Provider.Broadcast和Service. 其中Activity可以跨进程调用其他应用程序的Activity: Content Pro

*Android跨进程通信的四种方式

由于android系统中应用程序之间不能共享内存.因此,在不同应用程序之间交互数据(跨进程通讯)就稍微麻烦一些.在android SDK中提供了4种用于跨进程通讯的方式.这4种方式正好对应于android系统中4种应用程序组件:Activity.Content Provider.Broadcast和Service.其中Activity可以跨进程调用其他应用程序的Activity:Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应