概述
在进行进程间通信的过程中,如何服务端进程由于某种原因异常终止,我们的远程调用就会失败,影响我们的功能,那么怎么样能够知道服务端进程是否终止了呢,那就是给Binder设置死亡代理,下面看看如何设置。
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected: " + name +"--service--" + service);
mBookManager = IBookManager.Stub.asInterface(service);
Log.d(TAG, "mBookManager: " + Thread.currentThread().getName());
mBound = true;
if (mBookManager != null) {
Book book = new Book(1,"AA");
try {
mBookManager.addBook(book);
//设置死亡代理
mBookManager.asBinder().linkToDeath(mDeathRecipient,0);
for (Book book2 : mBookManager.getBookList()) {
Log.d(TAG, "onServiceConnected: " + book2);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
}
};
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
if (mBookManager == null) return;
mBookManager.asBinder().unlinkToDeath(mDeathRecipient,0);//解除死亡通知,如果Binder死亡了,不会在触发binderDied方法
mBookManager = null;
}
};
在onServiceConnected连接到远程服务以后,我们通过AIDL接口的asBinder方法获取到Binder对象,然后·调用linkToDeath
方法为其设置一个死亡代理DeathRecipient对象,这个对象有一个binderDied方法,当服务端进程异常终止,而我们尝试去绑定的时候,就会回调这个方法,我们可以在这个方法中进行对应的处理,例如重新绑定远程服务等。
另外,通过Binder中的下面两个方法,也可以判断
/**//检查Binder对象是否存在
* Check to see if the object still exists.
*
* @return Returns false if the
* hosting process is gone, otherwise the result (always by default
* true) returned by the pingBinder() implementation on the other
* side.
*/
public boolean pingBinder();
/**//检查Binder所在的进程是否存活
* Check to see if the process that the binder is in is still alive.
*
* @return false if the process is not alive. Note that if it returns
* true, the process may have died while the call is returning.
*/
public boolean isBinderAlive();
注意:如果你调用的是本地Binder,那么isBinderAlive方法永远返回true,因为你能调用Binder,说明你的进程肯定是存在的。
其他问题
1.当服务端进程终止时,如果我们客户端退出时(不是退到后台),会出现如下的异常信息
意思是Service连接泄漏,那是因为我们没有在当前页面退出时解除绑定,正确的写法如下
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mBookConnection);//页面销毁的时候接触原来绑定的服务
}
2.当我们通过下面的方式去绑定远程服务时,会出错
Intent intent = new Intent("com.lxn.getbook");
bindService(intent,mBookConnection,BIND_AUTO_CREATE);
错误信息如下
意思是说Service的Intent必须是显式的,这是因为 Android5.0中service的intent一定要显性声明, 当这样绑定的时候不会报错,正确写法如下
Intent intent = new Intent("com.lxn.getbook");
intent.setPackage("com.example.server");//指定Service进程所在的包名
bindService(intent,mBookConnection,BIND_AUTO_CREATE);