绑定服务是客户端-服务器接口中的服务器。绑定服务可让组件(例如 Activity)绑定到服务、发送请求、接收响应,甚至执行进程间通信 (IPC)。 绑定服务通常只在为其他应用组件服务时处于活动状态,不会无限期在后台运行。
绑定服务是 Service类的实现,可让其他应用与其绑定和交互。要提供服务绑定,您必须实现 onBind()回调方法。该方法返回的 IBinder
对象定义了客户端用来与服务进行交互的编程接口。
public class LocalService extends Service {
private IBinder mBind=new LocalBinder();
/**
* 返回的 IBinder 对象定义了客户端用来与服务进行交互的编程接口
*/
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBind;
}
/**
* LocalBinder 为客户端提供 getService() 方法,以检索 LocalService 的当前实例
*/
public class LocalBinder extends Binder{
LocalService getService(){
return LocalService.this;
}
}
public void getLog(){
Log.d("TAG", "getLog: 我是LocalService的log");
}
}
客户端可通过调用 [bindService()](https://developer.android.com/reference/android/content/Context.html?hl=zh-cn#bindService(android.content.Intent, android.content.ServiceConnection, int))绑定到服务。调用时,它必须提供 ServiceConnection的实现,后者会监控与服务的连接。[bindService()](https://developer.android.com/reference/android/content/Context.html?hl=zh-cn#bindService(android.content.Intent, android.content.ServiceConnection, int))方法会立即无值返回,但当 Android 系统创建客户端与服务之间的连接时,会对 ServiceConnection
调用 [onServiceConnected()](https://developer.android.com/reference/android/content/ServiceConnection.html?hl=zh-cn#onServiceConnected(android.content.ComponentName, android.os.IBinder)),向客户端传递用来与服务通信的 IBinder。
public class MainActivity extends AppCompatActivity {
LocalService service;
boolean mBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder iBinder) {
LocalService.LocalBinder binder = (LocalService.LocalBinder) iBinder;
service = binder.getService();
service.getLog();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mBound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
使用 Messenger
与 AIDL 比较
当您需要执行 IPC 时,为您的接口使用Messenger要比使用 AIDL 实现它更加简单,因为 Messenger会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。
如需让服务与远程进程通信,则可使用 Messenger 为您的服务提供接口。利用此方法,您无需使用 AIDL 便可执行进程间通信 (IPC)。
服务实现一个 Handler,由其接收来自客户端的每个调用的回调
Handler用于创建 Messenger对象(对 Handler的引用)
-
Messenger创建一个 IBinder,服务通过 onBind()使其返回客户端
public class MessengerService extends Service { /** Command to the service to display a message */ static final int MSG_SAY_HELLO = 1; /** * Handler of incoming messages from clients. */ class IncomingHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SAY_HELLO: Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); break; default: super.handleMessage(msg); } } } /** * Target we publish for clients to send messages to IncomingHandler. */ final Messenger mMessenger = new Messenger(new IncomingHandler()); /** * 绑定到服务时,我们返回一个接口给我们的messenger为服务发送消息。 */ @Override public IBinder onBind(Intent intent) { Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); return mMessenger.getBinder(); } }
messenger类方法
public IBinder getBinder() {
return mTarget.asBinder();
}
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
客户端只需根据服务返回的IBInder创建一个 Messenger,然后利用 send()发送一条消息。
public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
管理绑定服务的生命周期
当服务与所有客户端之间的绑定全部取消时,Android 系统便会销毁服务(除非还使用 [onStartCommand()](https://developer.android.com/reference/android/app/Service.html?hl=zh-cn#onStartCommand(android.content.Intent, int, int))启动了该服务)。因此,如果您的服务是纯粹的绑定服务,则无需对其生命周期进行管理 — Android 系统会根据它是否绑定到任何客户端代您管理。
不过,如果您选择实现 [onStartCommand()](https://developer.android.com/reference/android/app/Service.html?hl=zh-cn#onStartCommand(android.content.Intent, int, int))回调方法,则您必须显式停止服务,因为系统现在已将服务视为已启动。在此情况下,服务将一直运行到其通过 stopSelf()自行停止,或其他组件调用 stopService()为止,无论其是否绑定到任何客户端。
此外,如果您的服务已启动并接受绑定,则当系统调用您的 onUnbind()方法时,如果您想在客户端下一次绑定到服务时接收 onRebind()调用,则可选择返回 true。onRebind() 返回空值,但客户端仍在其 [onServiceConnected()](https://developer.android.com/reference/android/content/ServiceConnection.html?hl=zh-cn#onServiceConnected(android.content.ComponentName, android.os.IBinder))
回调中接收 IBinder。