Android 进程间通讯Binder异常总结

DeadObjectException:

Binder 为CS架构,我们无法确保Client端的生命周期,如被forcestop或被卸载等等。如果server端提供了接口回调的方式,一旦Client被停用,那么就会出现DeadObjectException的异常,原因是在Server进行Callback时,Client端已经死亡。

安卓本身提供了一些检测方法,拿com.android.server.location.RemoteListenerHelper来举例,

GpsStatus在注册时会通过LocationManager-->LocationManagerService-->.........-->最终会注册到com.android.server.location.RemoteListenerHelper

这是一个典型的跨进程服务,由LocationManager对外提供服务,

LocationManager.addGpsStatusListener();这个方法注册到了system_server内,进行卫星的状态变更等。

系统是这样进行处理的:

 public boolean addListener(@NonNull TListener listener) {
    ......
    ......
        LinkedListener deathListener = new LinkedListener(listener);
        synchronized (mListenerMap) {
            if (mListenerMap.containsKey(binder)) {
                // listener already added
                return true;
            }
            try {
                binder.linkToDeath(deathListener, 0 /* flags */);
            } catch (RemoteException e) {
                // if the remote process registering the listener is already death, just swallow the
                // exception and continue
                Log.e(mTag, "Remote listener already died.", e);
                return false;
            }


            mListenerMap.put(binder, deathListener);
            ......
            ......
        }
        return true;
    }

注意加粗部分,lintToDeath,注册了死亡通知,在Client binder死亡后会进行Callback,我们可以在Callback内进行逻辑处理,这里需要一个实现了IBinder.DeathRecipient接口的对象,方法如下:

   private class LinkedListener implements IBinder.DeathRecipient {
......
......
        @Override
        public void binderDied() {
            Log.d(mTag, "Remote Listener died: " + mListener);
            removeListener(mListener);
        }

    }

加粗部分,一旦被Client Binder死亡后 就会在这里进行Callback,我们可以在这里进行逻辑处理,如这里的逻辑是,如果Client Binder死亡,那么就反注册掉卫星的Callback。

这种是framework里比较常用的做法。


如果Callback 被Client主动清除,那么需要进行unlinkToDeath的操作,代码如下:

  public boolean removeListener(@NonNull TListener listener) {
        ......
        if (linkedListener != null) {
            binder.unlinkToDeath(linkedListener, 0 /* flags */);
        }
        return true;
    }

用户主动调用removeListener。


---------------------

通过判断binder是否存活等也是一种简易的解决方案:

如:

在需要进行Callback的地方,进行判断:

Binder.isBinderAlive,代码如下

            if (!jBinder.isBinderAlive()) {
                // The hosting process of the provider has died; we can't
                // use this one.
                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
                        + ": existing object's process dead");
                //Do some thing
                return null;
            }

如果binder已经死亡,do something you want




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值