AndroidのIBinderの生存確認について

最近Androidでプロセス間通信処理を書いた際にIBinderの生存確認方法を調べたのでメモ。

まず基本、Androidのプロセス間通信はaidlファイルにinterfaceを記載し、
クラスで実装後、相手側にIBinderインスタンスとして渡すことで通信が出来るようになる。

ActivityとServiceで通信を行う場合のコードはこんな感じになると思われる。

MyServiceInterface.aidl

interface MyServiceInterface {
    int add(int x, int y);
}

MyService.java

public class MyService extends Service implements MyServiceInterface.Stub {
    IBinder onBind(Intent intent) {
        return this;
    }

    @Override
    int add(int x, int y) {
        return x + y;
    }
    ~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~
}

MyClient.java

public class MyClient extends Activity {
    MyServiceInterface mService;

    @Override
    void onCreate((Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = new Intent(MyService.class.getName());
        bindService(intent, myServiceConn, BIND_AUTO_CREATE);
    }

    ServiceConnection myServiceConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = MyServiceInterface.Stub.asInterface(service);
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    }
~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~
    private void calc(int x, int y) {
        if (mService != null) {
            try {
                int result = mService.add(x, y);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~
}

このような形でプロセス間通信の処理を書いた場合、Service側が異常時等で死んでいると、
ActivityからServiceの処理を実行する際にDeadObjectExceptionが発生することがある。
RemoteExceptionの子クラスなのでcatchは出来るのだが、
ServiceがDeadObjectになっているか確認する方法が何か無いか気になったので調べてみた。

プロセス間で受け渡しを行っているIBinderには相手と通信できるか確認するため、
pingBinder()というメソッドが定義されている。
pingBinder()を使用すると通信ができる場合はtrue、通信ができない場合はfalseが返されるため、
相手が生きているか確認することができるようだ。

IBinderのインスタンスを保持したままという状況はあまり無いかもしれないが、
そのような状況になった場合はpingBinder()を使用した処理を試してみたい。