客户端经过调用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(); } }