Android 通过AIDL在服务之间传递活动对象

Android 通过AIDL在服务之间传递活动对象,android,android-service,aidl,android-binder,Android,Android Service,Aidl,Android Binder,我正在尝试为不同包中的多个服务共享一个公共对象。每个服务必须调用相同的对象 例如,服务A(来自APK A)实例化了一个自定义对象,我希望服务B和C(来自APK B和C)检索这个对象的引用并调用它的某个方法 我在Android参考中发现,应该可以使用: 活动对象 Parcel的一个不寻常的功能是读写活动数据的能力 物体。对于这些对象,对象的实际内容不是 写入,而不是写入引用对象的特殊标记。 从地块读回对象时,不会得到新的 对象的实例,而是在精确 与最初编写的对象相同。有两种形式的活动 对象可用 B

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

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

我在Android参考中发现,应该可以使用:

活动对象

Parcel的一个不寻常的功能是读写活动数据的能力 物体。对于这些对象,对象的实际内容不是 写入,而不是写入引用对象的特殊标记。 从地块读回对象时,不会得到新的 对象的实例,而是在精确 与最初编写的对象相同。有两种形式的活动 对象可用

Binder对象是Android通用跨进程的核心功能 通信系统。IBinder接口描述了一个摘要 具有绑定对象的协议。任何这样的接口都可以写入 一个包裹,阅读后,您将收到原始对象 实现该接口或一个特殊的代理实现 将调用传回原始对象。使用的方法是 writeStrongBinder(IBinder)、writeStrongInterface(IInterface), readStrongBinder(),writeBinderArray(IBinder[]), readBinderArray(IBinder[]),createBinderArray(), writeBinderList(列表)、readBinderList(列表)、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);
  }
}
public类CustomObject扩展绑定器实现可包裹{
公共自定义对象(){
超级();
}
public static final Parcelable.Creator=新建Parcelable.Creator(){
公共CustomObject createFromParcel(地块中){
IBinder i=in.readStrongBinder();
//如何检索引用??
返回null;
}
@凌驾
公共CustomObject[]新数组(整数大小){
返回null;
}
};
@凌驾
公共int描述内容(){
返回0;
}
@凌驾
公共无效写入包裹(包裹目的地,内部标志){
目的地写入活页夹(本);
}
}
有人已经这样做了吗


提前谢谢

你研究过吗?

这里有两种方法

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

    ICustomObject getCustomObject();
    
  • 在服务A中,在您已经得到的
    存根
    类中,只需返回从
    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的项目之间共享生成的类。

在我深入研究了这个问题之后,我认为这实际上是不可能做到的。您得到的ClassCastException是将
BinderProxy
(扩展IBinder的私有类)强制转换到实际类(
CustomObject
)的结果。当跨其他进程引用绑定时,
BinderProxy
似乎总是被传递,当它们声明“实现该接口的原始对象或特殊代理实现”时,这就是它们引用的对象。
BinderProxy
确实允许您调用的
onTransact()
方法,但不允许调用其他方法


老实说,我认为文档说明“原始对象”是通过进程传递的,这是不正确的,因为该类的文档还有其他几个实例。

我不想只共享数据。为此,一个简单的AIDL机制就足够了。我需要的是共享一个复杂的对象,该对象必须是唯一的,并且具有所有服务都可以调用的某些方法。您知道如何做到这一点吗?我几年前就试过了,后来放弃了。现在,我用与您相同的问题/结果再次尝试。不幸的是,没有。。对于这个项目,我更改了我的流程,以便在每次调用对象上的方法时检索对象的副本。虽然不完美,但它很有效。但我仍然有兴趣知道这个问题是否有解决办法