我正在尝试为不同包中的多个服务共享一个公共对象。每个服务必须调用同一个对象。
例如,服务A(来自APK A)实例化自定义对象,我希望服务B和C(来自APK B和C)检索此对象的引用并调用它的某些方法。
我在Android参考资料中发现应该可以使用Parcel:
有效对象
Parcel的一个不寻常的功能是读写活动的能力 对象。对于这些对象,对象的实际内容不是 写入,而不是引用该对象的特殊标记。 从包裹中读取对象时,您没有得到新的 对象的实例,而是一个操作精确的句柄 最初写的同一个对象。有两种形式的活跃 对象可用。
Binder对象是Android一般跨进程的核心工具 通讯系统。 IBinder接口描述了一个摘要 具有Binder对象的协议。任何这样的接口都可以写入 包裹,在阅读时,您将收到原始对象 实现该接口或特殊的代理实现 将回调传递回原始对象。使用的方法是 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);
}
}
有人已经这样做了吗?
提前致谢!
答案 0 :(得分:2)
以下是两种方法。
ICustomObject.aidl
。在这种情况下,你不需要使对象Parcelable。你可能甚至不需要编写上面的代码;只需在另一个中使用一种AIDL描述的类型。例如,将这样的行添加到服务A的主AIDL中:
ICustomObject getCustomObject();
在服务A中,在您已经获得的Stub
课程中,您只需返回从ICustomObject
继承的内容。
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的项目之间共享结果类。
答案 1 :(得分:0)
你看过content providers吗?
答案 2 :(得分:0)
在对自己进行相当广泛的调查后,我认为实际上并没有这样做。您获得的ClassCastException是将BinderProxy
(这是一个扩展IBinder的私有类)强制转换为实际类(CustomObject
)的结果。当引用其他进程中的Binders时,似乎总是传递BinderProxy
,这是当它们声明“实现该接口的原始对象或特殊代理实现”时它们所引用的对象。 BinderProxy
允许您调用IBinder的onTransact()
方法,但没有其他方法。
老实说,当他们声明“原始对象”是跨进程传递时,我认为文档是不正确的,因为该类的文档的其他几个实例是both blatantly copy-pasted and wrong。