1. 程式人生 > >安卓四大元件之bindService使用

安卓四大元件之bindService使用

bindServer使用場景

1、在同個app之間呼叫(即是同一個程序中)

2、在不同app之間呼叫(即是跨程序間通訊)

同個app間呼叫(只有一次啟動該服務)

BinderActicityA

public class BinderActicityA extends Activity implements View.OnClickListener {     private Button btn1;     private Button btn2;     private Button btn3;     private Button btn4;     private BindService bindService = null;     private boolean isBound = false;       private ServiceConnection conn = new ServiceConnection() {           @Override         public void onServiceConnected(ComponentName name, IBinder service) {             isBound = true;             BindService.MyBinder binder = (BindService.MyBinder) service;             bindService = binder.getService();             int num = bindService.getRandomNumber();             Log.v("hjz","numA="+num);         }           //client 和service連線意外丟失時,會呼叫該方法         @Override         public void onServiceDisconnected(ComponentName name) {             Log.v("hjz","onServiceDisconnected  A");         }     };       @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_binder_main);         findLayoutView();         setLister();         initData();       }       private void findLayoutView() {         btn1 = (Button) findViewById(R.id.btn1);         btn2 = (Button) findViewById(R.id.btn2);         btn3 = (Button) findViewById(R.id.btn3);         btn4 = (Button) findViewById(R.id.btn4);     }       private void setLister() {         btn1.setOnClickListener(this);         btn2.setOnClickListener(this);         btn3.setOnClickListener(this);         btn4.setOnClickListener(this);     }       private void initData() {       }       @Override     public void onClick(View v) {         Intent intent = null;         switch (v.getId()){             case R.id.btn1:                 intent = new Intent(BinderActicityA.this, BindService.class);                 intent.putExtra("from", "ActivityA");                 bindService(intent,conn,BIND_AUTO_CREATE);                 break;             case R.id.btn2:                 if (isBound){                     isBound = false;                     Log.v("hjz","ActicityA is unbindService");                     unbindService(conn);                 }                 break;             case R.id.btn3:                 intent = new Intent(this, BinderActivityB.class);                 startActivity(intent);                 break;             case R.id.btn4:                 this.finish();                 break;         }     }       @Override     protected void onDestroy() {         super.onDestroy();         Log.i("hjz", "ActivityA -> onDestroy");     } }

xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:paddingBottom="@dimen/activity_vertical_margin"     android:paddingLeft="@dimen/activity_horizontal_margin"     android:paddingRight="@dimen/activity_horizontal_margin"     android:paddingTop="@dimen/activity_vertical_margin"     android:orientation="vertical"     tools:context="com.hh.servicedemo.MainActivity">       <Button         android:id="@+id/btn1"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="BinderService繫結"/>       <Button         android:id="@+id/btn2"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="BinderService解綁"/>       <Button         android:id="@+id/btn3"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="跳轉到BinderActivityB"/>       <Button         android:id="@+id/btn4"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:text="finish"/>     </LinearLayout>

BinderService

public class BindService extends Service {       public class MyBinder extends Binder{           public BindService getService(){             return BindService.this;         }     }     //通過binder實現了 呼叫者(client)與 service之間的通訊     private MyBinder binder = new MyBinder();       private final Random generator = new Random();       @Override     public void onCreate() {         super.onCreate();         Log.i("hjz","BindService -> onCreate, Thread: " + Thread.currentThread().getName());     }       @Override     public IBinder onBind(Intent intent) {         Log.i("hjz", "BindService -> onBind, Thread: " + Thread.currentThread().getName());         return binder;     }       @Override     public boolean onUnbind(Intent intent) {         Log.i("hjz", "BindService -> onUnbind, from:" + intent.getStringExtra("from"));         return false;     }       @Override     public int onStartCommand(Intent intent, int flags, int startId) {         Log.i("hjz", "BindService -> onStartCommand, startId: " + startId + ", Thread: " + Thread.currentThread().getName());         return START_NOT_STICKY;     }       @Override     public void onDestroy() {         Log.i("hjz", "BindService -> onDestroy, Thread: " + Thread.currentThread().getName());         super.onDestroy();     }       //在Service中暴露出去的方法,供client呼叫     public int getRandomNumber(){         return generator.nextInt();     } }

點選BinderService繫結,再點選BinderService解綁,最後點選finish,列印日誌

07-09 11:46:49.360 29714-29714/com.hh.servicedemo I/hjz: BindService -> onCreate, Thread: main 07-09 11:46:49.360 29714-29714/com.hh.servicedemo I/hjz: BindService -> onBind, Thread: main 07-09 11:46:49.380 29714-29714/com.hh.servicedemo V/hjz: numA=1859239539 07-09 11:46:50.650 29714-29714/com.hh.servicedemo V/hjz: ActicityA is unbindService 07-09 11:46:50.650 29714-29714/com.hh.servicedemo I/hjz: BindService -> onUnbind, from:ActivityA 07-09 11:46:50.650 29714-29714/com.hh.servicedemo I/hjz: BindService -> onDestroy, Thread: main 07-09 11:46:52.290 29714-29714/com.hh.servicedemo I/hjz: ActivityA -> onDestroy

點選BinderService繫結,再點選finish 07-09 11:48:07.260 29714-29714/com.hh.servicedemo I/hjz: BindService -> onCreate, Thread: main 07-09 11:48:07.260 29714-29714/com.hh.servicedemo I/hjz: BindService -> onBind, Thread: main 07-09 11:48:07.270 29714-29714/com.hh.servicedemo V/hjz: numA=-341510490 07-09 11:48:09.290 29714-29714/com.hh.servicedemo I/hjz: ActivityA -> onDestroy 07-09 11:48:09.310 29714-29714/com.hh.servicedemo I/hjz: BindService -> onUnbind, from:ActivityA 07-09 11:48:09.310 29714-29714/com.hh.servicedemo I/hjz: BindService -> onDestroy, Thread: main

先從BinderService來分析,從列印可以看出,先呼叫onCreate,接著在呼叫onBind方法,你會發現使用binderStart來啟動,onStartCommand這方法不呼叫;在Service中執行順序: 1、先得到相應的binder物件,可以在Service內部用內部類得到相應的binder,如下所示:

 public class MyBinder extends Binder{           public BindService getService(){             return BindService.this;         }     }     //通過binder實現了 呼叫者(client)與 service之間的通訊     private MyBinder binder = new MyBinder(); 2、在onBind方法中返回IBinder例項,返回例項可以是Service例項本身 或者 通過binder暴露出Service公共方法。通常情況下,就是講binder弄成Service內部類,然後在binder中建立一個類似getService的方法並返回包含binder的Service物件,如上面那種情況,這樣client(客戶端)可以通過該方法得到相應的Service例項

接著 呼叫者(client客戶端)執行的流程

1、先建立ServiceConnetion例項,並重寫其方法,如下面所示:

//建立ServiceConnection型別的例項     private ServiceConnection conn = new ServiceConnection() {           @Override         public void onServiceConnected(ComponentName name, IBinder service) {             isBound = true;             BindService.MyBinder binder = (BindService.MyBinder) service;             bindService = binder.getService();             int num = bindService.getRandomNumber();             Log.v("hjz","numA="+num);         }           //client 和service連線意外丟失時,會呼叫該方法         @Override         public void onServiceDisconnected(ComponentName name) {             Log.v("hjz","onServiceDisconnected  A");         }     }; 這是因為使用bindServer中使用到該物件,bindServer原始碼 @Override     public boolean bindService(Intent service, ServiceConnection conn,             int flags) {//呼叫bindServer,發現第二個傳參就是ServiceConnection物件         return mBase.bindService(service, conn, flags);     }

2、當執行了onServiceConnected回撥時,我們可以通過IBinder例項得到Service例項物件 或 直接呼叫binder公共方法,這樣就實現了client和service的連線 3、client和Service解除繫結時,onServiceDisconnected並不會被呼叫;onServiceDisconnected被呼叫的情況是發生在client和Service連線意外丟失時,這時client和Service一定是斷開連線了。

同個app間呼叫(多次呼叫該服務)

BinderAcivityB

public class BinderActivityB extends Activity implements View.OnClickListener {     private Button btn1;     private Button btn2;     private Button btn4;       private BindService bindService = null;     private boolean isBound = false;       private ServiceConnection conn = new ServiceConnection() {           @Override         public void onServiceConnected(ComponentName name, IBinder service) {             isBound = true;             BindService.MyBinder binder = (BindService.MyBinder) service;             bindService = binder.getService();             int num = bindService.getRandomNumber();             Log.v("hjz","numB="+num);         }           @Override         public void onServiceDisconnected(ComponentName name) {             Log.v("hjz","onServiceDisconnected  B");         }     };       @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_binder_b);         findLayoutView();         setLister();         initData();       }       private void findLayoutView() {         btn1 = (Button) findViewById(R.id.btn1);         btn2 = (Button) findViewById(R.id.btn2);         btn4 = (Button) findViewById(R.id.btn4);     }       private void setLister() {         btn1.setOnClickListener(this);         btn2.setOnClickListener(this);         btn4.setOnClickListener(this);     }       private void initData() {       }       @Override     public void onClick(View v) {         Intent intent = null;         switch (v.getId()){             case R.id.btn1:                 intent = new Intent(BinderActivityB.this, BindService.class);                 intent.putExtra("from", "ActivityB");                 bindService(intent,conn,BIND_AUTO_CREATE);                 break;             case R.id.btn2:                 if (isBound){                     isBound = false;                     Log.v("hjz","ActicityB is unbindService");                     unbindService(conn);                 }                 break;             case R.id.btn4:                 this.finish();                 break;         }     }       @Override     protected void onDestroy() {         super.onDestroy();         Log.i("hjz", "ActivityB -> onDestroy");     } } 在binderA中, 點選 binderA繫結→跳轉BinderAcitivityB→binderB繫結→binderB解綁→BinderB finish→BinderA解綁→BinderA finish 的日誌 07-09 13:16:10.030 8593-8593/com.hh.servicedemo I/hjz: BindService -> onCreate, Thread: main 07-09 13:16:10.030 8593-8593/com.hh.servicedemo I/hjz: BindService -> onBind, Thread: main 07-09 13:16:10.050 8593-8593/com.hh.servicedemo V/hjz: numA=665064614 07-09 13:16:13.650 8593-8593/com.hh.servicedemo V/hjz: numB=1116469133 07-09 13:16:16.550 8593-8593/com.hh.servicedemo V/hjz: ActicityB is unbindService 07-09 13:16:18.680 8593-8593/com.hh.servicedemo I/hjz: ActivityB -> onDestroy 07-09 13:16:22.920 8593-8593/com.hh.servicedemo V/hjz: ActicityA is unbindService 07-09 13:16:22.930 8593-8593/com.hh.servicedemo I/hjz: BindService -> onUnbind, from:ActivityA 07-09 13:16:22.950 8593-8593/com.hh.servicedemo I/hjz: BindService -> onDestroy, Thread: main 07-09 13:16:25.660 8593-8593/com.hh.servicedemo I/hjz: ActivityA -> onDestroy 從列印日誌中發現

在client(客戶端)呼叫Service【同一個Service】情況下:

如果Service不存在,Service執行順序是onCreate→onBind,接著client建立ServiceConnection例項並執行onServiceConnected這個方法。

如果Service已處於執行狀態【說明在此之前已經在其他地方啟動過該Service】,由於之前執行過的onBind回撥獲取IBinder例項,該IBinder例項在所有的client(客戶端)之間是共享的,所以第二次執行onBind回撥,直接使用上次已經獲取的IBinder例項,並將其傳入到與之對應的onServiceConnected方法中,標誌著連線已經建立了起來,這時就有兩個或者多個client(客戶端)和Service綁定了。

client(客戶端)執行unbindServie的流程:

client與Service解除繫結時,Service先檢測是否還與其他client(客戶端)與其連線→

如果沒有,Service執行onUnbind方法,然後在執行onDestroy方法

如果有,Service不會執行onUnbind和onDestroy方法(從列印的日誌中可以得出這樣結論)

點選 binderA繫結→跳轉BinderAcitivityB→binderB繫結→binderB解綁→BinderB finish→BinderA finish 的日誌

07-09 13:19:58.340 8297-8297/com.hh.servicedemo I/hjz: BindService -> onCreate, Thread: main 07-09 13:19:58.360 8297-8297/com.hh.servicedemo I/hjz: BindService -> onBind, Thread: main 07-09 13:19:58.360 8297-8297/com.hh.servicedemo V/hjz: numA=2026321547 07-09 13:20:02.190 8297-8297/com.hh.servicedemo V/hjz: numB=-1586530569 07-09 13:20:04.140 8297-8297/com.hh.servicedemo V/hjz: ActicityB is unbindService 07-09 13:20:05.820 8297-8297/com.hh.servicedemo I/hjz: ActivityB -> onDestroy 07-09 13:20:07.080 8297-8297/com.hh.servicedemo I/hjz: ActivityA -> onDestroy 07-09 13:20:07.110 8297-8297/com.hh.servicedemo I/hjz: BindService -> onUnbind, from:ActivityA 07-09 13:20:07.110 8297-8297/com.hh.servicedemo I/hjz: BindService -> onDestroy, Thread: main 結論:當client與Service通過bindServer連線起來之後,如果client(客戶端)執行(onDestroy)銷燬,那麼client會自動與Service解除繫結。

點選 binderA繫結→跳轉BinderAcitivityB→binderB繫結→BinderB finish→BinderA解綁→BinderA finish 的日誌 07-09 13:17:40.320 8297-8297/com.hh.servicedemo I/hjz: BindService -> onCreate, Thread: main 07-09 13:17:40.320 8297-8297/com.hh.servicedemo I/hjz: BindService -> onBind, Thread: main 07-09 13:17:40.340 8297-8297/com.hh.servicedemo V/hjz: numA=-1117645606 07-09 13:17:43.460 8297-8297/com.hh.servicedemo V/hjz: numB=1774346322 07-09 13:17:44.770 8297-8297/com.hh.servicedemo I/hjz: ActivityB -> onDestroy 07-09 13:17:56.780 8297-8297/com.hh.servicedemo V/hjz: ActicityA is unbindService 07-09 13:17:56.780 8297-8297/com.hh.servicedemo I/hjz: BindService -> onUnbind, from:ActivityA 07-09 13:17:56.780 8297-8297/com.hh.servicedemo I/hjz: BindService -> onDestroy, Thread: main 07-09 13:17:58.060 8297-8297/com.hh.servicedemo I/hjz: ActivityA -> onDestroy

點選 binderA繫結→跳轉BinderAcitivityB→binderB繫結→BinderB finish→BinderA finish 的日誌 07-09 13:21:22.890 8297-8297/com.hh.servicedemo I/hjz: BindService -> onCreate, Thread: main 07-09 13:21:22.890 8297-8297/com.hh.servicedemo I/hjz: BindService -> onBind, Thread: main 07-09 13:21:22.900 8297-8297/com.hh.servicedemo V/hjz: numA=1947324308 07-09 13:21:26.630 8297-8297/com.hh.servicedemo V/hjz: numB=-1343649013 07-09 13:21:27.730 8297-8297/com.hh.servicedemo I/hjz: ActivityB -> onDestroy 07-09 13:21:29.040 8297-8297/com.hh.servicedemo I/hjz: ActivityA -> onDestroy 07-09 13:21:29.060 8297-8297/com.hh.servicedemo I/hjz: BindService -> onUnbind, from:ActivityA 07-09 13:21:29.060 8297-8297/com.hh.servicedemo I/hjz: BindService -> onDestroy, Thread: main 上面的日誌列印,下面用一張圖來總結一下client和Service操作流程:

在不同app之間呼叫這裡就不做介紹了,有興趣的自己可以去研究一下

---------------------  作者:花姓-老花  來源:CSDN  原文:https://blog.csdn.net/zjws23786/article/details/51865238  版權宣告:本文為博主原創文章,轉載請附上博文連結!