3

我有一个通过 AIDL 导出 RPC 接口的 Android 服务。该接口是面向连接的,客户端将连接到它,与它进行交易,然后在退出时断开连接。

不幸的是客户端异常退出,例如被系统杀死,它永远没有机会告诉RPC接口连接已经关闭。这导致了问题。

当新客户端从接口附加和分离时,服务有什么方法可以自动得到通知?我找到了onBind()and onUnbind(),但它们不是一回事;他们告诉我接​​口是否在使用中。onUnbind()仅在最后一个客户端分离时才被调用。

有任何想法吗?(而且服务的设计受外部需求控制,无法更改……)

更新:我完全忘了提到我已经看过了linkToDeath(),它几乎完全符合我的要求,但它似乎只能以相反的方式工作——它允许客户端在服务终止时得到通知。当我尝试它时,似乎什么也没发生。文档有点零散;任何人都知道这是否按我想要的方式工作?如果是这样,如何让它告诉我哪个客户死了?

更新更新:我已经解决了这个问题,但只是作弊。我重新定义了它。我的应用程序实际上主要是使用 NDK 用 C 语言编写的,因此服务的设计很奇怪;因此,我将问题转移到 C 世界并创建了一个小型辅助进程,它使用 Unix 域套接字直接与我的应用程序的本机部分对话。它速度快,非常小,几乎是防弹的——但它仍然在作弊。所以虽然我的问题现在已经解决了,但我仍然想知道实际的答案是什么。

4

2 回答 2

3

通过在客户端初始化新对象并通过 AIDL 将其发送到服务来使用linkToDeath() (但反过来做) 。 然后您可以在您的服务中注册到您的客户的DeathRecipient,并在客户的进程异常退出时得到框架的通知。Binder

代码示例 -

在您的 .AIDL 文件中- 创建一个将Binder对象从客户端传递到服务的方法

void registerProcessDeath(in IBinder clientDeathListener);

在客户端- 初始化一个新对象并通过 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());
}

在服务方面- 获取客户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);
    }
};

附加阅读 - 这个机制在框架内非常常见,以防止进程死亡时的内存泄漏 - Alex Lockwood 关于此主题的非常好的教程

于 2016-07-15T16:56:08.127 回答
2

也许linkToDeath()可以在这里提供帮助。

于 2011-10-27T20:35:11.443 回答