java - 当绑定(bind)的客户端断开连接时通知 Android 服务

标签 java android service client bind

我在远程进程中有一个 android 服务,它可以有来自不同客户端的多个绑定(bind)。我的问题是,当特定的绑定(bind)客户端意外断开连接(即客户端崩溃)时,服务如何得到通知? 我无法使用 onUnbind(),因为它只会在所有 客户端断开连接后调用。

public class MyService extends Service {

    final Messenger mServiceMessenger = new Messenger(new IncomingHandler());

    @Override
    public IBinder onBind(Intent intent) {
        return mServiceMessenger.getBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return Service.START_STICKY;
    }

    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
        // Handling messages logic...
        }
    }
}

最佳答案

这可以通过 Binder.linkToDeath() 机制来完成 - 你必须要求每个客户端发送它们发起的 new Binder() 对象,然后链接到他们(您的客户)的死亡。 我将解释如何使用 AIDL 执行此操作文件。

(您可以选择任何 android IPC 机制,只要您可以将 Binder 对象从您的客户端传递到您的服务即可)

代码示例 -

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

void registerProcessDeath(in IBinder clientDeathListener, String packageName);

在客户端 - 初始化一个新对象并通过 AIDL 接口(interface)将其传递给您的服务。

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 and the client's package name
    mIMyAidlInterface.registerProcessDeath(new Binder(),getPackageName());
}


在服务端 -

1. 获取客户端的Binder并注册到他的linkToDeath()
2. 使用助手类通过android 的IBinder.DeathRecipient 处理所有客户端类

public class MyService extends Service {
    //Helper class to handle all client's deaths.
    private volatile ClientsDeathWatcher mClientsList;

    @Override
    public IBinder onBind(Intent intent) {
        mClientsList = new ClientsDeathWatcher();
        return mStub;
    }

    private final IMyAidlInterface.Stub mStub = new IMyAidlInterface.Stub() {

        @Override
        public void registerProcessDeath(IBinder cb, String packageName){

            boolean isRegistered = mClientsList.register(cb , packageName);
        }
    };
}
//This is thread-safe helper class to handle all 
//the client death related tasks.

//All you care abut is the clientDeath() method. 
public class ClientsDeathWatcher {

    private ArrayMap<String, DeathCallBack> mCallbacks = new ArrayMap<>();

    private final class DeathCallBack implements IBinder.DeathRecipient {
        private String pn;
        private IBinder mBinder;

        DeathCallBack(String packageName,IBinder binder) {
            pn = packageName;
            mBinder = binder;
        }

        public void binderDied() {
            synchronized (mCallbacks) {
                mBinder.unlinkToDeath(this,0);
                clientDeath(pn);
            }
        }
    }

    //To be called only from thread-safe functions
    private void clientDeath(String packageName) {
        mCallbacks.remove(packageName);
        //Do your stuff here.
        //$$$$$$$$$
    }

    public boolean register(IBinder token, String packageName) {
        synchronized (mCallbacks) {
            try {
                if (!mCallbacks.containsKey(packageName)) {
                    DeathCallBack mDeathCallBack = new DeathCallBack(packageName,token);
                    mCallbacks.put(packageName, mDeathCallBack);
                    //This is where the magic happens
                    token.linkToDeath(mDeathCallBack, 0);
                }
                return true;
            } catch (RemoteException e) {
                e.printStackTrace();
                return false;
            }
        }
    }
}

关于java - 当绑定(bind)的客户端断开连接时通知 Android 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18078914/

相关文章:

Java hibernate SQL 错误 : check right syntax to use near 'condition, description, name, pictures, price, status, User_UserAddress_idUserAd' at line 1

android - Flutter:如何赋予彩色容器不透明度?

android - 感叹号错误?

java - 无法扫描jar文件:错误的魔数(Magic Number)

java - Eclipse 中位置信息指定不正确

java - Android App Widget,变量正在重启

c++ - 从 Windows 服务检测 SD 卡插入?

Activity 终止后,Android 粘性服务未重新启动

java - 扩展 CrudRepository 并仍然使用 Spring Data JPA 为自定义方法创建自己的实现

Android:在 attachBaseContext 中使用 DataStore