Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中跨進程通信傳遞Parcelable對象時出現android.os.BadParcelableException: ClassNotFoundException when unmarsh

Android中跨進程通信傳遞Parcelable對象時出現android.os.BadParcelableException: ClassNotFoundException when unmarsh

編輯:關於Android編程

 

按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.CreatorCREATOR=new
            Parcelable.Creator(){
              @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端獲取數據的代碼如下:

 

ArrayListbeanList=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,那要怎麼辦呢?

其實很簡單,只需要在Client端讀取Bundle中的數據之前加上如下一行代碼:

 

bundle.setClassLoader(getClass().getClassLoader());
這樣就會使用apk classloader加載。

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved