我在包A(signerclient)中有一个活动,在包B(myservice)中有一个服务
活动的ResultReceiver:

private ResultReceiver resultreceiver = new ResultReceiver(null) {
            @Override
            protected void onReceiveResult(int resultCode, Bundle resultData) {
            ...
            }
        };

启动服务:
Intent intent = new Intent("com.example.STARTSERVICE");
intent.putExtra("resultreceiver", resultreceiver);
startService(intent);

接收端:
 ResultReceiver rr = (ResultReceiver) intent.getParcelableExtra("resultreceiver");

当客户机和服务器在同一个包中时执行此操作可以正常工作。但在这种情况下我得到:
FATAL EXCEPTION: IntentService[MyService]
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: com.example.cryptoclient.SignerClient$1
at android.os.Parcel.readParcelable(Parcel.java:1883)
at android.os.Parcel.readValue(Parcel.java:1771)
at android.os.Parcel.readMapInternal(Parcel.java:2008)
at android.os.Bundle.unparcel(Bundle.java:208)
at android.os.Bundle.getParcelable(Bundle.java:1100)
at android.content.Intent.getParcelableExtra(Intent.java:3396)
at org.axades.service.MyService.onHandleIntent(MyService.java:28)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.os.HandlerThread.run(HandlerThread.java:60)

我错过了什么?我的想法有可能吗?

最佳答案

是的,你的想法是可能的。引发ClassNotFoundException异常是因为您正试图对在不同进程中由不同的ClassLoader创建的类进行解压缩。
ResultReceiver类实现了适合进程间调用(ipc)的Parcelable接口,但是要读取服务中的对象,您需要使用用于在客户端应用程序(即活动中)中创建对象的相同类加载器。要在服务端获取类加载器,请调用传递客户机包名和标志组合的方法。这将返回客户端上下文对象,从中可以获得正确的类加载器对象。
例子:

public int onStartCommand(Intent intent, int flags, int startId) {
  try {

// assuming SignerClient activity is located in the package "com.example.client.A"
    Context context = createPackageContext("com.example.client.A", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
    ClassLoader cl = context.getClassLoader();

    Bundle bundle = intent.getExtras();
    bundle.setClassLoader(cl);
    ResultReceiver rr = bundle.getParcelable("resultreceiver");

//... your interaction with ResultReceiver ...
    rr.send(1, null);   // will result in a onReceiveResult call in the client activity

  } catch (NameNotFoundException e) {
    Log.e("MyService", "SignerClient package context was not found", e);
    throw new RuntimeException(e);
  }
  return START_STICKY;
}

我刚刚把它用在我的代码中-就像一个符咒。
更新
不过,我建议考虑使用createPackageContext而不是CONTEXT_INCLUDE_CODE。它实现CONTEXT_IGNORE_SECURITY接口,不需要扩展,因此类加载器问题是不可能的。它也是Messenger
更新2
如果您仍然喜欢使用ResultReceiver请查看Parcelable。它看起来比复杂的上下文操作更干净和简单。

07-25 21:06