Dav*_*ven 3 android android-service android-binder
我有一个 Android 服务,它通过 AIDL 导出 RPC 接口。该接口是面向连接的,客户端将连接到它,与其进行事务处理,然后在退出时断开连接。
不幸的是,客户端异常退出,例如被系统杀死,它永远没有机会告诉RPC接口连接已关闭。这导致了问题。
当新客户端附加到接口或从接口分离时,有什么方法可以让服务自动收到通知吗?我找到了onBind()和onUnbind(),但它们不是同一件事;他们告诉我该接口是否正在使用。onUnbind()仅当最后一个客户端分离时才会被调用。
有任何想法吗?(并且服务的设计是由外部需求控制的,无法更改......)
更新:我完全忘记提及我已经看过了linkToDeath(),它几乎完全符合我的要求,但它似乎只是以相反的方式工作——它允许客户端在服务终止时收到通知。当我尝试时,似乎什么也没发生。文档有点不完整;有人确定这是否能按我想要的方式工作吗?如果是这样,如何让它告诉我哪个客户死了?
更新更新:我已经解决了这个问题,但只是通过作弊。我重新定义了它。我的应用程序实际上主要是使用 NDK 用 C 语言编写的,因此该服务的设计很奇怪;因此,我将问题转移到 C 世界中,并创建了一个小型帮助程序进程,该进程使用 Unix 域套接字直接与我的应用程序的本机部分进行对话。它速度快、体积小、几乎防弹——但它仍然是作弊行为。因此,虽然我的问题现在已经解决了,但我仍然想知道实际的答案是什么。
通过在客户端初始化新对象并通过 AIDL 将其发送到服务来使用linkToDeath() (但反之亦然) 。
然后,您可以在服务内注册到客户端的DeathRecipient,并在客户端进程异常退出时收到框架通知。Binder
代码示例 -
.AIDL 在文件内部- 创建一个方法将Binder对象从客户端传递到服务
void registerProcessDeath(in IBinder clientDeathListener);
Run Code Online (Sandbox Code Playgroud)
在客户端- 初始化一个新对象并通过 AIDL 接口将其传递给您的服务。
public void onServiceConnected(ComponentName className, IBinder service) {
mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
//Call the registerProcessDeath method from the AIDL file and pass
//the new Binder object
mIMyAidlInterface.registerProcessDeath(new Binder());
}
Run Code Online (Sandbox Code Playgroud)
在服务端- 获取客户的Binder并注册到他的linkToDeath().
private IBinder mBinder; //Instance variable
private final IMyAidlInterface.Stub mStub = new IMyAidlInterface.Stub() {
@Override
public void registerProcessDeath(IBinder clientDeathListener) {
mBinder = clientDeathListener;
//Create new anonymous class of IBinder.DeathRecipient()
clientDeathListener.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
//Do your stuff when process exits abnormally here.
//Unregister from client death recipient
mBinder.unlinkToDeath(this,0);
}
},0);
}
};
Run Code Online (Sandbox Code Playgroud)
附加阅读 - 这种机制在框架内非常常见,以防止进程死亡时发生内存泄漏 - Alex Lockwood 就该主题提供了非常好的教程。
| 归档时间: |
|
| 查看次数: |
7169 次 |
| 最近记录: |