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);
}
}
}