Android进程间通信有很多种,这里记录使用Service和Messenger来通信。在开始之前需要了解一下Android组件之Service。
Aandroid组件使用Service有两种方式,一种是启动方式,第二种是绑定方式。因为第一种启动方式,在启动Service之后,不会得到Service的任何返回,所以对Service的控制不是很好,没有更多的交互。而第二种绑定方式,在Android绑定Service之后,Service会给调用方组件返回一个IBinder对象。这样的方式就可以进行进程间通信。
下面看服务端代码:
//服务端
public class MessengerService extends Service {
private static final String TAG = "MessengerService";
private static final int MESSAGE_TYPE_ONE = 1;
private static final int MESSAGE_TYPE_TEO = 2;
private static final int MESSAGE_TYPE_THR = 3;
private Messenger messenger;
public MessengerService() {
messenger = new Messenger(new MyHandler());
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
}
@Override
public IBinder onBind(Intent intent) {
if(intent!=null){
Log.d(TAG, "onBind: return ok");
return messenger.getBinder();
}else{
Log.d(TAG, "onBind: handler null");
return null;
}
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
}
static class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Messenger messenger = msg.replyTo;
Message message = null;
Bundle bundle = new Bundle();
switch (msg.what){
case MESSAGE_TYPE_ONE:{
message = Message.obtain(null,1);
bundle.putString("msg","hello one");
break;
}
case MESSAGE_TYPE_TEO:{
message = Message.obtain(null,2);
bundle.putString("msg","hello teo");
break;
}
case MESSAGE_TYPE_THR:{
message = Message.obtain(null,3);
bundle.putString("msg","hello three");
break;
}
}
try {
if (message!=null) {
message.setData(bundle);
messenger.send(message);
}else {
Log.d(TAG, "handleMessage: message null");
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
上述代码中,与平常的绑定Service方式略有不同,这里不用创建内部Binder子类,但是需要创建一个Messenger对象,onBinder方法返回的IBinder是Messenger中的IBinder。客户端接收到这个Binder之后,使用这个Binder创建一个Messenger对象,这样客户端与服务端的Messenger对象使用同一个IBinder,进程间通信就没有问题了。
客户端代码:
//客户端
private void initServiceConnection(){
Log.d(TAG, "initServiceConnection: ");
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemoteMessenger = new Messenger(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mRemoteMessenger = null;
}
};
}
private void initMessenger(){
Log.d(TAG, "initMessenger: ");
messenger = new Messenger(new MyHandler());
}
private void bindService(){
Log.d(TAG, "bindService: ");
Intent intent = new Intent();
intent.setPackage("com.junxu.servicelearn");
intent.setAction("com.junxu.servicelearn.MyBinderService");
bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
}
private void unBindService(){
Log.d(TAG, "unBindService: ");
unbindService(serviceConnection);
}
private void sendMessage(){
Log.d(TAG, "sendMessage: ");
try {
Message message = Message.obtain(null,1);
message.replyTo = messenger;
mRemoteMessenger.send(message);
} catch (RemoteException e) {
Log.d(TAG, "sendMessage: "+e.getMessage());
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
}
static class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d(TAG, "handleMessage: "+msg.getData().getString("msg"));
}
}
可以看到,客户端创建Messenger对象的时候,传入了IBinder对象,这个IBinder对象是服务器端返回来的。发送消息的时候使用的是这个Messenger对象。在客户端还创建了一个Messenger对象,这个对象创建的时候传入一个Handler对象,这个Messenger对象是传递到服务端的,供服务端回复消息的使用。从上面服务端代码可以看到,发送消息的Messenger对象是从客户端接收到的Message对象中获取的。而创建这个Messenger对象的时候传入的Handler就是用于处理服务端返回消息的。
另一个需要注意点:客户端绑定Service的时候。使用的是隐式绑定,这里的intent不单止需要设置action还需要设置包名,否则会报错:Service Intent must be explicit: Intent。这是Android5.0之后隐式绑定Service的一个更改