Andriod死亡通知メカニズムを利用してサービスにクライアントがkillされたと伝えた.

8192 ワード

Androidは、特定のアプリケーションのニーズを満たすために死亡通知と呼ばれるメカニズムを提供しています.
あるプロセスは別のプロセスが生存しているかどうかを知る必要がある.あるいは、あるプロセスがkillされたとき、別のプロセスはこのことを知ることを望んでいます.
一般的には、あるboundサービスがクライアントがkillされているかどうかに関心を持っています.
なぜサービスがクライアントにkillされたのかと聞かれるかもしれません.
適用シーン:
たとえば、boundサービスはbindから来たclientにリソースを割り当てる可能性があります.clientがreleaseまたはunbindを呼び出すとリソースが解放されますが、
ある時clientは確かにkillされ、サービスが知らない場合、割り当てられたリソースは解放されません.
AndroidはDeathRecipientというインタフェースを提供しています.
1.clientで1つのBinderをnewし、次に別のプロセスに送信します.通常はBoundサービスです.
2.別のプロセスの死亡情報に関心を持つプロセス(通常はサービス)でDeathRecipientを実現するだけです
3.クライアントから送信されたbinderを呼び出すlinkToDeathメソッド
public abstract void linkToDeath (IBinder.DeathRecipient recipient, int flags)
Added in  API level 1
Register the recipient for a notification if this binder goes away. If this binder object unexpectedly goes away (typically because its hosting process has been killed), then the given  IBinder.DeathRecipient 's  DeathRecipient.binderDied()  method will be called.
You will only receive death notifications for remote binders, as local binders by definition can't die without you dying as well.
Throws
RemoteException
if the target IBinder's process has already died.
See Also
  • unlinkToDeath(IBinder.DeathRecipient, int)

  • DeathRecipient is an interface for receiving a callback when the process hosting an IBinder has gone away.
    DeathRecipientについては、公式サイトのドキュメントを参照してください.
    http://developer.android.com/reference/android/os/IBinder.DeathRecipient.html
    -------------------------------------------
    テスト手順、appを起動し、startをクリックし、adb shell psでcomを表示します.example.testserviceプロセスID、adb shell kill pidでclient killを落とし、logをチェック
    Log.d(TAG, "client has died");printが出てくるかどうか
    Sample code:
    //Client  TestActivity.java
    public class TestActivity extends Activity {     private String TAG = "TestService";     private Button mStartBtn;     private Button mStopBtn;     private Button mBindBtn;     private Button mUnbindBtn;     ClickListener mClickListener = new ClickListener();     private Intent mIntent = new Intent("com.example.action.TEST");     private IBinder mBinder = new Binder();     private ITest mTest = null;     private ServiceConnection mServiceConnection = new ServiceConnection() {                  @Override         public void onServiceDisconnected(ComponentName name) {            //TODO Auto-generated method stub             Log.d(TAG, "onServiceDisconnected");                     }                  @Override         public void onServiceConnected(ComponentName name, IBinder service) {            //TODO Auto-generated method stub             Log.d(TAG, "onServiceConnected:"+ name);             mTest = ITest.Stub.asInterface(service);             try {                 mTest.setBinder(mBinder);             } catch (RemoteException e) {                //TODO Auto-generated catch block                 e.printStackTrace();             }         }     };     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_test_service);         mStartBtn = (Button)findViewById(R.id.start);         mStopBtn = (Button)findViewById(R.id.stop);         mBindBtn = (Button)findViewById(R.id.bind);         mUnbindBtn = (Button)findViewById(R.id.unbind);         mStartBtn.setOnClickListener(mClickListener);         mStopBtn.setOnClickListener(mClickListener);         mBindBtn.setOnClickListener(mClickListener);         mUnbindBtn.setOnClickListener(mClickListener);              }     @Override     public boolean onCreateOptionsMenu(Menu menu) {        //Inflate the menu; this adds items to the action bar if it is present.         getMenuInflater().inflate(R.menu.activity_test_service, menu);         return true;     }          private class ClickListener implements OnClickListener{         @Override         public void onClick(View v) {             int id = v.getId();             if(id == R.id.start){                 startService(mIntent);                              }else if(id == R.id.stop){                 stopService(mIntent);             }else if(id == R.id.bind){                 bindService(mIntent, mServiceConnection,  Context.BIND_AUTO_CREATE);             }else if(id == R.id.unbind){                 unbindService(mServiceConnection);             }                      }              } }
    //ITest .aidl package com.example.testservice;/** Example service interface */interface ITest {
        int getPid();     void setBinder(IBinder client);     }
    //TestService.java
    public class TestService extends Service{     private String TAG = "TestService";          private TestApi mTestApi = new TestApi();          private IBinder mClient = null;     @Override     public IBinder onBind(Intent intent) {         Log.d(TAG, "Onbind() action="+ intent.getAction());         return mTestApi;     }          private class TestDeathRecipient implements DeathRecipient{         @Override         public void binderDied() {             Log.d(TAG, "client has died");         }              }          private class TestApi extends ITest.Stub{         @Override         public int getPid() throws RemoteException {             return (int)Thread.currentThread().getId();         }         @Override         public void setBinder(IBinder client) throws RemoteException {             mClient = client;             mClient.linkToDeath(new TestDeathRecipient(), 0);         }              } }
    //AndroidManifest.xml
        package="com.example.testservice"    android:versionCode="1"    android:versionName="1.0">             android:minSdkVersion="8"        android:targetSdkVersion="17"/>             android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme">                     android:name="com.example.testservice.TestActivity"            android:label="@string/app_name">                                                                                              android:process=":service">                                                    
    //activity_test_service.xml
        xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".TestActivity">             android:id="@+id/textView1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:layout_centerVertical="true"        android:text="@string/hello_world"/>             android:id="@+id/start"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:layout_toLeftOf="@+id/stop"        android:text="start"/>             android:id="@+id/bind"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignLeft="@+id/start"        android:layout_below="@+id/start"        android:layout_marginTop="23dp"        android:text="Bind"/>             android:id="@+id/stop"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:layout_alignRight="@+id/textView1"        android:text="stop"/>             android:id="@+id/unbind"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignBottom="@+id/button1"        android:layout_toRightOf="@+id/button1"        android:text="Unbind"/>