binder服务端监听客户端销毁,利用linkToDeath自动移除客户端回调监听

binder场景是客户端绑定服务端,可以通过linkToDeath方法监听服务端的消亡,防止远程调用抛出RemoteException的异常。

但是如果服务端有客户端添加的回调,客户端销毁了。服务端在不知道情况下回调了客户端添加的回调。服务端就会抛出RemoteException异常或者空指针异常,造成服务端崩溃。

以下代码就是放在服务端,管理客户端添加过来的回调类。当客户端异常销毁,服务端自动维护回调集合,自动移除不存在的客户端回调。


import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.util.Log;

import java.util.Collection;
import java.util.HashMap;

/**
 * 解决binder的客户端绑定到服务端后,客户端销毁(Death)后没有主动解除绑定,当服务端回调后抛出RemoteException异常或空指针异常
 * Helper class to hold client's binder interface.
 *
 *
 */
public class BinderInterfaceContainer<T extends IInterface> {

    private static final String TAG="BinderInterfaceContainer";

    public static class BinderInterface<T extends IInterface>  implements IBinder.DeathRecipient {
        public final T binderInterface;
        private final BinderInterfaceContainer<T> mContainer;

        public BinderInterface(BinderInterfaceContainer<T> container, T binderInterface) {
            mContainer = container;
            this.binderInterface = binderInterface;
        }

        @Override
        public void binderDied() {
            //解除消亡回调
            binderInterface.asBinder().unlinkToDeath(this, 0);
            mContainer.handleBinderDeath(this);
        }
    }

    /**
     * 暴露回调给外部使用
     * @param <T>
     */
    public interface BinderEventHandler<T extends IInterface> {
        void onBinderDeath(BinderInterface<T> bInterface);
    }

    private final BinderEventHandler<T> mEventHandler;
    private final HashMap<IBinder, BinderInterface<T>> mBinders = new HashMap<>();



    public BinderInterfaceContainer( BinderEventHandler<T> eventHandler) {
        mEventHandler = eventHandler;
    }

    public BinderInterfaceContainer() {
        mEventHandler = null;
    }

    /**
     * 添加需要回调的binder
     * @param binderInterface
     */
    public void addBinder(T binderInterface) {
        IBinder binder = binderInterface.asBinder();
        synchronized (this) {
            BinderInterface<T> bInterface = mBinders.get(binder);
            if (bInterface != null) {
                return;
            }
            bInterface = new BinderInterface<T>(this, binderInterface);
            try {
                //添加销亡回调
                binder.linkToDeath(bInterface, 0);
            } catch (RemoteException e) {
                throw new IllegalArgumentException(e);
            }
            mBinders.put(binder, bInterface);
        }
    }

    /**
     * 手动移除需要回调的binder
     * 客户端消亡会自动回调,仅在逻辑需要时候,手动断开时候需要调用
     * @param binderInterface
     */
    public void removeBinder(T binderInterface) {
        IBinder binder = binderInterface.asBinder();
        synchronized(this) {
            BinderInterface<T> bInterface = mBinders.get(binder);
            if (bInterface == null) {
                return;
            }
            binder.unlinkToDeath(bInterface, 0);
            mBinders.remove(binder);
            Log.d(TAG,"removeBinder-->"+binderInterface);
        }
    }

    /**
     * 读取指定的binder回调
     * @param binderInterface
     * @return
     */
    public BinderInterface<T> getBinderInterface(T binderInterface) {
        IBinder binder = binderInterface.asBinder();
        synchronized (this) {
            return mBinders.get(binder);
        }
    }

    /**
     * 添加binder回调接口
     * @param bInterface
     */
    public void addBinderInterface(BinderInterface<T> bInterface) {
        IBinder binder = bInterface.binderInterface.asBinder();
        synchronized (this) {
            try {
                binder.linkToDeath(bInterface, 0);
            } catch (RemoteException e) {
                throw new IllegalArgumentException(e);
            }
            mBinders.put(binder, bInterface);
        }
    }

    public Collection<BinderInterface<T>> getInterfaces() {
        synchronized (this) {
            return mBinders.values();
        }
    }

    public synchronized int size() {
        return mBinders.size();
    }

    public synchronized void clear() {
        Collection<BinderInterface<T>> interfaces = getInterfaces();
        for (BinderInterface<T> bInterface : interfaces) {
            removeBinder(bInterface.binderInterface);
        }
    }

    private void handleBinderDeath(BinderInterface<T> bInterface) {
        removeBinder(bInterface.binderInterface);
        if (mEventHandler != null) {
            mEventHandler.onBinderDeath(bInterface);
        }
    }
}

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Binder 中,服务端可以通过 IBinder 类中的 transact() 方法向客户端发送消息。下面是一个简单的示例代码,演示了如何在服务端中向客户端发送消息: 1.服务端代码 ```java public class MyService extends Service { private MyBinder mBinder = new MyBinder(); public class MyBinder extends Binder { public void sendMessage(String message) { Parcel data = Parcel.obtain(); data.writeString(message); // 获取客户端的 IBinder IBinder clientBinder = getApplicationContext() .getServiceManager() .getService("com.example.client"); try { clientBinder.transact(0, data, null, IBinder.FLAG_ONEWAY); } catch (RemoteException e) { e.printStackTrace(); } finally { data.recycle(); } } } @Override public IBinder onBind(Intent intent) { return mBinder; } } ``` 在服务端代码中,我们定义了一个 MyBinder 对象,并实现了 sendMessage() 方法。在 sendMessage() 方法中,我们创建了一个 Parcel 对象,将消息写入 Parcel 中,然后获取客户端的 IBinder 对象,并通过 transact() 方法向客户端发送消息。 2.客户端代码 ```java public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String message = intent.getStringExtra("message"); Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); } } ``` 在客户端代码中,我们定义了一个 BroadcastReceiver 对象,用于接收服务端发送的消息。在 onReceive() 方法中,我们获取到消息,并使用 Toast 将其显示出来。 需要注意的是,服务端在通过 transact() 方法向客户端发送消息时,需要获取客户端的 IBinder 对象。在上面的示例代码中,我们使用了 getApplicationContext().getServiceManager().getService("com.example.client") 来获取客户端的 IBinder 对象,其中 "com.example.client" 是客户端的包名。如果客户端没有在系统服务中注册,服务端将无法获取客户端的 IBinder 对象,从而无法向客户端发送消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写点啥呢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值