Android远程服务回调

13

我有一个带AIDL接口的远程服务,被多个客户端应用程序使用。我想为需要一定时间的调用添加异步方法,但需要保证解决方案是安全的,意味着只有我的应用程序可以与服务通信。客户端应用程序签名与服务应用程序相同。目前,这些应用程序只是绑定到服务并调用单个接口方法执行各种操作。

一种选择是在操作完成时从服务中广播Intent,并在客户端应用程序中使用BroadcastReceiver,但问题#1是,这能否以确保只有我的应用程序可以接收Intent的方式完成? setPackage()似乎可以做到这一点,但我需要支持Gingerbread设备,根据此答案,该方法不可行:setPackage for intent in gingerbread

因此,我需要添加第二个.aidl接口,用于服务使用的回调接口,由客户端实现。我见过在此处使用监听器的示例,但我不确定与客户端仅将第二个接口对象作为参数传递有何区别(如来自此答案的IScript / IScriptResult示例:Service call backs to activity in android)

问题#2,在这里使用监听器与回调方法相比有什么好处?


3
监听器就是回调方法。 - CommonsWare
1个回答

28
回调方法/监听器是正确的选择(正如CommonsWare所说,它几乎是相同的东西)。我会说,这比摆弄BroadcastReceiver要简单得多,因为你已经在使用aidl。
像这样:
IAsyncThing.aidl:
package com.my.thingy;

import com.my.thingy.IAsyncThingListener;

interface IAsyncThing {
  void doSomething(IAsyncThingListener listener);
}

IAsyncThingListener.aidl:

package com.my.thingy;

import com.my.thingy.IAsyncThingListener;

interface IAsyncThingListener {
  void onAsyncThingDone(int resultCodeIfYouLike);
}

您可以通过在服务上使用签名级别权限来强制只有您的应用程序可以绑定到该服务(请参见此处关于“服务权限”的注释:http://developer.android.com/guide/topics/security/permissions.html)。具体来说:

  • 在您的服务的AndroidManifest.xml中声明权限。确保它是signature级别。
  • 将该权限添加到您的service标记中
  • 在所有其他应用程序中,使用uses-permission来使用它。

还有一些需要注意的事项:

  • 在调用方中,您需要对IAsyncThingListener.Stub进行子类化。您的调用应用程序代码可能已经对其他内容进行了子类化,因此这意味着您必须使用额外的(可能是内部)类来接收完成通知。我之所以提到这一点,仅因为这可能是第二个问题的答案——我不完全理解。
  • 如果服务可能在与调用方不同的进程中,则每个进程都应使用IBinder.linkToDeath注册对另一个进程的死亡通知。

如果我的服务调用回调函数,但绑定的应用程序不再处于活动状态/已移至后台或被系统杀死,会发生什么? - Android QS
5
这就是 IBinder.linkToDeath 的作用。如果应用程序被终止,您将得到通知。在所有其他情况下(例如它在后台),所有IPC通信应该仍然正常工作。 - Adrian Taylor
如果应用程序的活动绑定到我的服务并发出异步请求,但在回调被调用时不再处于活动状态(不在屏幕上),那么回调函数仍然会被接收到吗?当活动被销毁时,私有回调存根对象不会被销毁吗? - Android QS
2
IAsyncThingListener.aidl 中的导入行有什么原因吗? - ingh.am
1
@ingh.am 是的,您必须在aidl文件中导入所有非标准类型,否则它将无法编译。 - Robyer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接