2013/02/12

Android:DeathRecipientで他プロセスの死亡を検知する


Androidには他プロセスの死亡を検知する仕組みとしてDeathRecipientクラスが用意されています。
DeathRecipientは対象となるIBinderのホストプロセスの死亡をモニタします。

IBinder.DeathRecipient
http://developer.android.com/reference/android/os/IBinder.DeathRecipient.html

プロセス間通信時に、相手プロセスがkillされたタイミングを知ることができます。


●サンプルコード

下記はDeathRecipientを使用したサンプルコードです。
mDeathRecipient = new IBinder.DeathRecipient() {
    @Override
    public void binderDied() {
        if (mBinder != null)
            mBinder.unlinkToDeath(this, 0);
    }
};

mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder binder) {
        mBinder = binder;
        mBinder.linkToDeath(mDeathRecipient, 0);
    }
    ....
}
IBinderのホストプロセスが死亡するとbinderDied()がコールバックされます。


●ServiceConnection.onServiceDisconnectedとの違い

ServiceConnection.onServiceDisconnected()も同じような機能を持っています。
# というより、onServiceDisconnectedはDeathRecipient.binderDied()をトリガとしています。
# 参照:android.app.LoadedApk$DeathMonitor

ただし、サービスとの接続状態によっては次のような違いが出てきます。
【サービスバインド状態でのサービスホストプロセス死亡】
  • onServicedisconnectedがコールされる
  • binderDiedがコールされる

【非サービスバインド状態(サービスアンバインド後)のサービスホストプロセス死亡】
  • onServicedisconnectedはコールされない
  • binderDiedがコールされる

これは、
"サービスとの接続状態をモニタする(ServiceConnection)"
か、
"IBinderのホストプロセスの死亡をモニタする(DeathRecient)"
かの違いによるものです。


●API

・linkToDeath
対象となるBinderのホストプロセスが死亡した時の通知を受け取るRecipientを登録します。
ターゲットであるBinderが既に死亡している場合はRemoteExceptionが投げられます。

・unlinkToDeath
対象となるIBinderのホストプロセス死亡のモニタを解除します。
既に登録解除されたRecipientを引数指定するとNoSuchElementExceptionが投げられます。


●ちなみに

当然ですが、DeathRecipientは自プロセスの死亡まではlistenできません。
自プロセスがkillされると、登録したDeathRecipientインスタンスもろもろ解放されます。