客戶端經過調用bindService方法可以綁定服務,而後Android系統會調用服務的onBind回調方法,這個方法會返回一個跟服務端交互的IBinder對象。這個綁定是異步的,bindService方法當即返回,而且不給客戶端返回IBinder對象。要接受IBinder對象,客戶端必須建立一個ServiceConnection類的實例,而且把這個實例傳遞給bindService方法。java
注意:只有Activity、Service和內容提供器(content provider)可以綁定服務,廣播接收器是不能綁定服務的。android
經過綁定服務來實現功能有如下幾個步驟:
app
實現一個ServiceConnection接口,並重寫裏面的onServiceConnected和onServiceDisconnected兩個方法,其中,前者是在服務已經綁定成功後回調的方法,後者是在服務發生異常終止時調用的方法。異步
在客戶端,經過bindService方法來異步地綁定一個服務對象,若是綁定成功,則會回調ServiceConnection接口方法中的onServiceConnected方法,並獲得一個IBinder對象。ide
服務端經過建立一個*.aidl文件來定義一個能夠被客戶端調用的業務接口,同時,服務端還須要提供一個業務接口的實現類,並實現*.aidl中定義的全部方法,一般讓這個實現類去繼承Stub類。this
注意:建立aidl文件時有幾個注意點:spa
(1)定義的方法前面不能有修飾符,相似於接口的寫法。code
(2)支持的類型有:8大基本數據類型,CharSequence,String,List<String>,Map,以及自定義類型。orm
自定義類型須要作到如下幾點:xml
實現Parcelable接口。
定義一個aidl文件來聲明該類型。
若是要在其餘的aidl文件中使用,則必需要使用import來引用。
經過Service組件來暴露業務接口。
經過Service的onBind方法來返回被綁定的業務對象。
客戶端若是綁定成功,就能夠像調用本身的方法同樣去調用遠程的業務對象方法。
爲了便於理解,能夠看一看下面的這個項目,項目名爲ServiceINS。
先來看看項目的構成:
MainActivity:
package com.example.serviceins; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { private ICat cat; private boolean isBound = false;// 用於判斷是否綁定 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // 綁定服務的鏈接回調接口 private ServiceConnection conn = new ServiceConnection() { // 已經綁定完成時調用 @Override public void onServiceConnected(ComponentName name, IBinder service) { // 綁定成功後回調的方法 cat = ICat.Stub.asInterface(service); isBound = true; Toast.makeText(MainActivity.this, "綁定成功", Toast.LENGTH_SHORT) .show(); } // 服務發生異常終止時調用的方法 @Override public void onServiceDisconnected(ComponentName name) { isBound = false; } }; // 綁定服務 public void boundClick(View view) { Intent intent = new Intent(this, MyBoundService.class); // 這個綁定的步驟是異步的,綁定成功後會回調onServiceConnected方法 bindService(intent, conn, Context.BIND_AUTO_CREATE); } // 解除綁定 public void unBoundClick(View view) { if (isBound) { unbindService(conn); Toast.makeText(MainActivity.this, "解除綁定成功", Toast.LENGTH_SHORT) .show(); } } // 經過IPC調用業務方法 public void callClick(View view) { if (cat == null) { return; } try { cat.setName("黑貓警長"); Toast.makeText(this, cat.desc() + "\n" + cat.getPerson().toString(), Toast.LENGTH_LONG).show(); } catch (RemoteException e) { e.printStackTrace(); } } }
activity_main.xml
<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:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="boundClick" android:text="綁定一個服務" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="unBoundClick" android:text="解除綁定服務" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="callClick" android:text="經過IPC調用業務方法" /> </LinearLayout>
ICat.aidl:
package com.example.serviceins; import com.example.serviceins.Person; interface ICat { void setName(String name); String desc(); }
ICatImpl:
package com.example.serviceins; import android.os.RemoteException; import com.example.serviceins.ICat.Stub; /* * 業務接口的具體實現類 */ public class CatImpl extends Stub { private String name; @Override public void setName(String name) throws RemoteException { this.name = name; } @Override public String desc() throws RemoteException { return "hello! my name is " + name + "," + "I am a police."; } }
MyBoundService:
package com.example.serviceins; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MyBoundService extends Service { public MyBoundService() { } @Override public void onCreate() { super.onCreate(); } @Override public IBinder onBind(Intent intent) { return new CatImpl(); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); } }