参考:https://developer.android.com/guide/components/bound-services.html
Messenger简介
如需让接口跨不同的进程工作,则可使用 Messenger 为服务创建接口。服务可以这种方式定义对应于不同类型 Message 对象的 Handler。此 Handler 是 Messenger 的基础,后者随后可与客户端分享一个 IBinder,从而让客户端能利用 Message 对象向服务发送命令。此外,客户端还可定义自有 Messenger,以便服务回传消息。
这是执行进程间通信 (IPC) 的最简单方法,因为 Messenger 会在单一线程中创建包含所有请求的队列,这样你就不必对服务进行线程安全设计。
与 AIDL 的比较
当你需要执行 IPC 时,为你的接口使用Messenger 要比使用 AIDL 实现它更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果你的服务必须执行多线程处理,则应使用 AIDL 来定义接口。
Messenger底层实现就是AIDL,只是对AIDL进行了封装,更加便于使用。
使用Messenger
服务端进程:
1、在服务中实现一个 Handler,由其接收来自客户端的每个调用的回调
2、Handler 用于创建Messenger 对象(对 Handler 的引用)
3、Messenger 创建一个 IBinder,服务通过onBind() 使其返回客户端
服务端的一般性代码如下所示:
public class MessengerServiceDemo extends Service {
/**
* Command to the service to display a message
*/
public static final int MSG_FROM_CLIENT = 1;
public static final String MSG_KEY_FROM_CLIENT = "MSG";
private static final String TAG = MessengerServiceDemo.class.getSimpleName();
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_FROM_CLIENT:
Log.i(TAG, "receice from client:" + msg.getData().get(MSG_KEY_FROM_CLIENT));
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
}
然后注册Service,让其运行在不同的进程:
<service
android:name=".MessengerServiceDemo"
android:enabled="true"
android:exported="true"
android:process=":remote" />
客户端进程:
客户端使用 IBinder 将 Messenger(引用服务的Handler)实例化,然后使用后者将 Message 对象发送给服务。
客户端的一般性代码如下所示:
public class MessengerActivity extends AppCompatActivity {
Messenger mService = null;
boolean mBound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_messenger);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = new Messenger(service);
mBound = true;
Message msg = Message.obtain(null, MessengerServiceDemo.MSG_FROM_CLIENT, 0, 0);
Bundle bundle=new Bundle();
bundle.putString(MessengerServiceDemo.MSG_KEY_FROM_CLIENT,"hi,this is client!");
msg.setData(bundle);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
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;
}
};
@Override
protected void onStart() {
super.onStart();
bindService(new Intent(this, MessengerServiceDemo.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
运行,打印Log如下所示,说明服务端接收到了客户端发来的消息!
01-28 20:11:59.926 6112-6112/com.easyliu.demo.messengerdemo:remote I/MessengerServiceDemo: receice from client:hi,this is client!
但是此时服务端是无法往客户端回传信息的,
如果需要服务端能够回复客户端,就和服务端一样,我们还需创建一个Handler并且创建一个新的Messenger,并把这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数就可以回应客户端。
客户端代码修改如下所示:
/**
* 处理从服务器端发来的信息
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MessengerService.MSG_FROM_SERVICE:
mCallbackText.setText("Received from service: " + msg.getData().get(MessengerService.MSG_KEY_FROM_SERVICE));
break;
default:
super.handleMessage(msg);
}
}
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
mService = new Messenger(service);
mCallbackText.setText("Attached.");
try {
//发送注册消息
Message msg = Message.obtain(null,
MessengerService.MSG_FROM_CLIENT);
msg.replyTo = mMessenger;//用于服务端回传信息
mService.send(msg);
} catch (RemoteException e) {
}
// As part of the sample, tell the user what happened.
Toast.makeText(MainActivity.this, R.string.remote_service_connected,
Toast.LENGTH_SHORT).show();
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
mCallbackText.setText("Disconnected.");
Toast.makeText(MainActivity.this, R.string.remote_service_disconnected,
Toast.LENGTH_SHORT).show();
}
};
服务端的代码如下,得到了客户端的Messenger之后就可以往客户端发送message了。
static final String MSG_KEY_FROM_SERVICE = "message";
static final int MSG_FROM_CLIENT = 1;
static final int MSG_FROM_SERVICE = 2;
/**
* 处理从客户端发来的消息
*/
static class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_FROM_CLIENT:
Messenger client=msg.replyTo;//得到客户端的Messenger
Message message = Message.obtain(null,
MessengerService.MSG_FROM_SERVICE);
Bundle bundle = new Bundle();
bundle.putString(MessengerService.MSG_KEY_FROM_SERVICE, "I have received message!");
message.setData(bundle);
try {
client.send(message);//服务端回传给客户端
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
以上就是利用Messenger实现客户端和服务端的双向通信。