AIDLによるサービスとの通信でBundleにParcelableをセットするとBadParcelableException
以前にも書いたが、以下の様なAIDLを定義してActivityとServiceで通信を行っている。
- IWebScrapingService.aidl
interface IWebScrapingService { boolean scrape(in String url, inout Bundle bundle); }
ActivityはServiceをバインドした後、スタブのメソッドを介してServiceのスクレイピングを実施する。
urlパラメタにはスクレイピング対象のURLを与えるが、bundleにどのような内容をセットするか(セットして貰うか)は実装クラスとそれを利用するActivityに任されており、例えば今書いているWebScrapingServiceでは、Bundleにそれぞれ
認証時のクレデンシャル
取得したいHTML要素のid値
取得したいHTML属性の名前
HTTP_STATUS (ステータスコード)
をセットして使用している。
ここからが本題だが、上記パラメタのbundleにセットできる型は、Bundleであり、それ自体はAIDLがサポートしているが、Bundleにセットする「名前-値」の組合わせもやはりAIDLの制約を受ける。
-
- Javaプリミティブ
- String, List, Map, CharSequence, AIDLに定義したインターフェース
- Parcelableを実装したクラス
従ってBaseInfoというParcelableを実装したクラスをService側で直接編集して貰おうと、以下のようにBundleにわざわざputParcelableセットすることにしたのだが、
Bundle bundle = new Bundle(); BaseInfo baseInfo = new BaseInfo(); bundle.putParcelable("baseInfo", baseInfo);
サービスのバインド時は問題が無いものの、メソッド実行時にBundleを読込む際表題の例外が発生してしまうのだ。
: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: attendroid.model.BaseInfo: at android.os.Parcel.readException(Parcel.java:1249) : at android.os.Parcel.readException(Parcel.java:1235) : at attendroid.service.IWebScrapingService$Stub$Proxy.scrape(IWebScrapingService.java:125) : at attendroid.CalendarActivity$CalendarSelectAction.getModel(CalendarActivity.java:123) : at java.lang.reflect.Method.invokeNative(Native Method) : at java.lang.reflect.Method.invoke(Method.java:521)
うーん、どうしてClassNotFoundExceptionなんだ。訳が分らない。
考えられるのはSun Javaでも散々苦労させられたクラスローダの問題だが、今の所原因は分らない。