5

我正在尝试为不同包中的多个服务共享一个公共对象。每个服务必须调用相同的对象。

例如,服务 A(来自 APK A)实例化了一个自定义对象,我希望服务 B 和 C(来自 APK B 和 C)检索该对象的引用并调用它的某些方法。

我在 Android 参考中发现使用Parcel应该是可能的:

活动对象

Parcel 的一个不同寻常的功能是能够读取和写入活动对象。对于这些对象,不会写入对象的实际内容,而是写入引用该对象的特殊标记。从 Parcel 中读回对象时,您不会获得该对象的新实例,而是获得一个句柄,该句柄对最初写入的完全相同的对象进行操作。有两种形式的活动对象可用。

Binder 对象是 Android 通用跨进程通信系统的核心设施。IBinder 接口描述了一个带有 Binder 对象的抽象协议。任何此类接口都可以写入 Parcel,并且在阅读时,您将收到实现该接口的原始对象或将回调通信回原始对象的特殊代理实现。使用的方法有 writeStrongBinder(IBinder)、writeStrongInterface(IInterface)、readStrongBinder()、writeBinderArray(IBinder[])、readBinderArray(IBinder[])、createBinderArray()、writeBinderList(List)、readBinderList(List)、createBinderArrayList() .

我试图通过 AIDL 传递我的对象(扩展活页夹)来做到这一点,但没有任何效果,当我试图从方法 createFromParcel(Parcel in) 检索引用时,我总是得到一个 ClassCastException。

我的代码示例:

public class CustomObject extends Binder implements Parcelable {

  public CustomObject() {
    super();
  }

  public static final Parcelable.Creator<CustomObject> CREATOR = new Parcelable.Creator<CustomObject>() {
  public CustomObject createFromParcel(Parcel in) {
    IBinder i = in.readStrongBinder();
      // HOW TO RETRIEVE THE REFERENCE ??
      return null;
    }

    @Override
    public CustomObject[] newArray(int size) {
      return null;
    }
  };

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

  @Override
  public void writeToParcel(Parcel dest, int flags) {
    dest.writeStrongBinder(this);
  }
}

有人已经这样做了吗?

提前致谢 !

4

3 回答 3

2

这里有两种方法。

简单:对对象本身使用aidl

  • 您似乎有一个现有的 AIDL 接口,您可以通过该接口将此“自定义对象”作为包裹传递。不要那样做。反而:
  • 您通过的对象本身应该由 AIDL 描述。比如说,你称它为ICustomObject.aidl
  • 在这种情况下,您不需要将对象设为 Parcelable。你可能甚至不需要编写上面的代码;只需在另一种中使用一种 AIDL 描述的类型。例如,在服务 A 的主 AIDL 中添加这样的一行:

    ICustomObject getCustomObject();
    
  • 在服务 A 中,在Stub您已经拥有的类中,您需要简单地返回继承自ICustomObject.

  • 在服务 B 和 C 中,您可以简单地调用该方法来获取ICustomObject. 简单的!没有包裹,没有readStrongBinder(),什么都没有。

更难

如果您执行上述操作,Android 工具链会生成编组和解组对象的 Java 代码。您可以自己编写代码。

ICustomObject myObjectWhichActuallyLivesInAnotherProcess = ICustomObject.Stub.asInterface(parcel.readStrongBinder())

甚至

ICustomObject myObjectWhichActuallyLivesInAnotherProcess = (ICustomObject)parcel.readStrongBinder().queryLocalInterface("com.your.custom.object");

但是,我认为如果您使一切都变得辅助,您的生活会更加理智。

关于课堂分享的注意事项

您可能想要创建一个包含在其中的 Android“库项目” ICustomObject.aidl,这样您就可以在构建 A、B 和 C 的项目之间共享生成的类。

于 2013-05-27T17:28:03.320 回答
0

你调查过内容提供商吗?

于 2013-05-27T07:04:54.887 回答
0

在我自己进行了相当广泛的研究之后,我认为它实际上无法完成。您得到的 ClassCastException 是将 a BinderProxy(这是一个扩展 IBinder 的私有类)转换为您的实际类 ( CustomObject) 的结果。BinderProxy当在其他进程中引用 Binders 时,似乎总是传递A ,这是他们在声明“实现该接口的原始对象或特殊代理实现”时引用的对象。BinderProxy确实允许您调用IBinderonTransact()的方法,但仅此而已。

老实说,当他们声明“原始对象”跨进程传递时,我认为文档是不正确的,因为该类的文档的其他几个实例都是公然复制粘贴和错误的

于 2015-09-20T21:42:14.227 回答