您的位置:首页 > 移动开发 > Android开发

Android 进程间通讯Binder异常总结

2017-11-07 14:00 344 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: