android 从 AIDL 绑定服务返回“活动”对象

Posted

技术标签:

【中文标题】android 从 AIDL 绑定服务返回“活动”对象【英文标题】:android returning a "live" object from an AIDL bound service 【发布时间】:2013-08-13 23:21:12 【问题描述】:

我想创建一个 AIDL 服务,由于缺少正确的术语,该服务会返回“活动”对象。也就是说,我想要这样的工作,

IFoo foo = myService.getFoo(x); // calls to myService service to get an IFoo
IBar bar = foo.getBar(y); // IPC to IFoo to get an IBar
IBaz baz = bar.getBaz(z); // IPC to IBar to get an IBaz

baz.setEnabled(false); // IPC to IBaz to modify the service's copy of IBaz

我希望这是可能的,但我可以找到一个很好的例子。另一种方法是做类似的事情,

myService.setBazEnabled(x, y, z, false);

前者是一种更面向对象的方法,而后者更实用。

【问题讨论】:

【参考方案1】:

只要 IFooIBarIBaz 都是通过 AIDL 定义的,就应该可以正常工作。

【讨论】:

通过“通过 AIDL 定义”,你的意思是我有一个 .aidl 接口给他们......然后我只返回一个实现该接口的对象?该对象是否需要为Parcelable?仅当它包含除了方法之外的数据? @JeffreyBlattman:“你的意思是我有一个 .aidl 接口给他们”——是的。 “那我只返回一个实现该接口的对象?” -- 不,你继承了.Stub,就像你对你的活页夹所做的那样。 “对象需要是 Parcelable 吗?” - 不,事实上,我怀疑这是否有效。 “只有当它包含除了方法之外的数据?” - 数据没有移动。 AIDL 公开方法。基本上,这是通过网络发送纯数据(例如 REST Web 服务)和通过网络发送纯行为(例如 SOAP Web 服务)之间的区别。 @JeffreyBlattman:我没有你的场景的例子,但我有一个相关的例子:回调。为了让您的客户端向服务提供回调对象,您需要定义回调 AIDL,让客户端实现 .Stub,并将该 .Stub 的实例传递给绑定器上接受回调实例的某个方法。该服务获取 AIDL 定义的接口的一个实例,并可以在其上调用方法。见github.com/commonsguy/cw-omnibus/tree/master/AdvServices/… 和github.com/commonsguy/cw-omnibus/tree/master/AdvServices/… 确实,您在第二条评论中的建议有效。我将编辑您的答案以提供一个明确的例子。 “数据没有移动。AIDL 暴露了方法。”——这是一个关键点。您要么返回操作,要么返回数据,但不能同时返回。 err,发布了一个新答案,以免破坏您的帖子。【参考方案2】:

在 CommonsWare 的评论 #2 中提供一个明确的建议示例 ...

首先,定义从主AIDL接口返回的子AIDL接口,

interface IMyService 
  IFoo getFoo();

IFoo本身应该是一个AIDL接口,

interface IFoo 
  ...

IMyService.getFoo() 的实现中,构造一个新的绑定器,并将其作为IFoo 接口返回,

public class MyService implements Service 
  public class FooBinder extends IFoo.Stub 
    ...
  

  public class MyBinder extends IMyService.Stub 
    @Override
    public IFoo getFoo() 
      return IFoo.Stub.asInterface(new FooBinder()); 
    

  @Override
  public IBinder onBind() 
    return new MyBinder();
  

【讨论】:

您应该能够返回new FooBinder(),而无需IFoo.Stub.asInterface()。事实上,我预计IFoo.Stub.asInterface() 会引起问题。 IFoo.Stub.asInterface(new FooBinder());new FooBinder() 都不能正常工作。调用IFoo 中的方法时,会从at android.os.Parcel.readException(Parcel.java:1624)得到java.lang.IllegalArgumentException: Format specifier: s错误

以上是关于android 从 AIDL 绑定服务返回“活动”对象的主要内容,如果未能解决你的问题,请参考以下文章

Android初级教程进程间的通信AIDL

从已绑定的服务返回不同的 Binder

[android] 采用aidl绑定远程服务

使用 AIDL 编写 Android 服务时如何为客户端分发自定义类

AIDL

在两个应用程序之间使用 AIDL 时未调用 onServiceConnected()