Service 部分
首先,新建一个Service
,要让这个Service跟UI运行在两个不同的进程上,只需在manifests里添加上Service的android:process
属性(进程名字而已,没有什么要求)。
<service
android:name=".MyService"
android:enabled="true"
android:exported="false"
android:process="ProcessName">
</service>
进程间通信是通过Message
进行的,而Massage由Messenger
转发和接受,所以我们要在通信两端各写一个Messenger
//send message to the IncomingHandler
final Messenger mMessenger =
new Messenger(new IncomingHandler());
这样一来,接到的消息都会通过IncommingHandler
处理,至于收到Message后具体怎么处理,就跟你在IncommingHandler里面是怎么重载 handleMessage()
有关了,这是一个例子:
//send message to the IncomingHandler
final Messenger mMessenger = new Messenger(new IncomingHandler());
private class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
Log.d("TAG","receive message 0");
break;
case 1:
Log.d("TAG","receive message 1");
break;
default:
super.handleMessage(msg);
}
}
}
注意,如果Handler中包含对Service或Activity其他成员或函数的引用,那么将影响到Service或Activity被回收,可能导致内存泄露。正确的做法是用
WeakReference
。
最后,在Service中重载回调函数onBind()
,每次被一个Activity绑定的时候,这个函数会被调用。
/* When clients 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();
}
Activity部分
前面说了,Messenger
是负责转发Message, Activity与Service之间的通信通过Message
进行,Service部分的Messenger大家应该都懂是怎么一回事了吧?可能我没有说清楚,十分欢迎留言或发邮件给我。现在介绍Activity部分。其实两边的写法都差不多,前面看懂了,后面就比较简单了。
首先,同样的在Activity里定义一个接收Message的Messenger,和一个处理接收到的Message的Handler。
//send message to the IncomingHandler
final Messenger mMessenger = new Messenger(new IncomingHandler());
要绑定Activity与Service,只需在onCreate()
或者其他需要的位置调用bindService()
函数就好了,需要传入的参数是:
1. Intent,就像跳转到其他的Activity一样写跳转到Service的Intent
2. ServiceConnection,马上就要将这部分了
3. 绑定的模式,一个常量,定义在Context里。
bindService(new Intent(this, MyService.class),
mConnection, Context.BIND_AUTO_CREATE);
其中mConnection是连接Service重要的参数,接下来介绍怎么写。
新建一个ServiceConnection类,重载两个函数onServiceConnected
和onServiceDisconnected
,这两个函数分别会在服务连接上和服务断开时被调用,直接上代码:
// Msg.java
// 定义消息名称
public static final int MSG_REGISTER = 0;
// 定义MSG_REGISTER的参数1可选值:
// Activity的代号,以区分绑定的Activity
public static final int ACTIVITY_MAIN = 1;
//...
// MainActivity.java
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 从Ibinder获取在Service那边传入的Messenger
mServiceMessenger = new Messenger(service);
mBounded = true;
// try块只是为了告诉Service“是我连上你的服务了!”
try {
//首先创建一个消息,为了避免重复创建,更好利用消息池,
//使用Message.obtain来创建。
//Msg.MSG_REGISTER是自己定义的一个整数,
//表示这个消息的内容是:注册(绑定)一个新的Activity
Message msg = Message.obtain(null, Msg.MSG_REGISTER);
msg.replyTo = mServiceMessenger;
msg.arg1 = Msg.ACTIVITY_MAIN;
mServiceMessenger.send(msg);
} catch (RemoteException e) {
Log.e("TAG","无法绑定服务");
}
}
@Override
public void onServiceDisconnected(ComponentName name){
mServiceMessenger = null;
mBounded = false;
}
};
至此,绑定的工作就已经全部介绍完毕了。
解除绑定
在Activity销毁的时候,我们一般希望显示的解绑,并在Service上做一些动作。
public void UnbindService(){
if (mBounded) {
getApplicationContext().
unbindService(mConnection);
mBounded = false;
}
}
用Messenger发送Message
以上两部分已经分别讲解了Service里和Activity里应该怎么写Messenger来接收消息,这部分将说明怎样用Messenger发送Message给对方。
方法很简单,
mMessenger.send(msg);
如果考虑得更细致一些,会在调用send()函数前先检测一下连接,检查一下mBounded
是否为true
,否则尝试重新绑定服务,像我这样,封装成一个函数:
public void sendToService(Message msg) {
if (mBounded && mMessenger != null) {
try {
mMessenger.send(msg);
Log.v(TAG, " sent " + msg.what);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
BindService();
}
} else {
BindService();
Log.e(TAG, "mMessenger is null or Service unbounded");
}
}