您的位置:首页 > 其它

Messenger实现多进程通信

2017-10-28 11:05 120 查看
Messenger进行多进程通信时一次处理一个请求,在服务端不用考虑线程同步的问题,因为服务端不存在并发执行的情况。它的作用主要是为了传递消息,如果需要跨进程调用服务端的方法就不适合使用。

用Messenger实现多线程通信时,服务端:

在服务端创建一个Service来处理客户端的连接请求,同时创建一个Handler并通过这个Handler来创建一个Messenger对象,然后在Service的onBaind方法中返回这个Messenger对象底层的Binder即可。代码如下:

public class MessengerService extends Service {

private static final int SAY_HOLLE = 0;

private static final String TAG = "MessengerService";

private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case SAY_HOLLE:
Log.e(TAG, "receive msg from client:" + msg.getData().getString("msg"));

break;
default:
super.handleMessage(msg);

}
}
}

private final Messenger mMessenger = new Messenger(new MessengerHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();

}
}

Service在Android Manifest文件中的注册为:

<service
android:name=".MessengerService"
android:exported="true"
android:enabled="true"
android:process=":remote"/>

通过Android Manifest文件中给Service指定process属性来实现与客户端处于不同的进程。

客户端:

客户端进程首先要绑定服务端的Service,绑定成功之后用服务端返回的IBinder对象创建一个Messenger,即通过onServiceConnected()方法中的IBinder service参数创建一个客户端的Messenger对象,然后通过这个Messenger就可以向服务端发送消息了,发送的消息是Message类型。(新建Message对象,Bundle对象,Bundle对象中放入需要往服务端发送的消息内容,然后将Bundle对象放进Message对象中,最后通过Messenger对象将该Message发送给服务端)代码如下图所示:

public class MainActivity extends AppCompatActivity {
private static final int SAY_HOLLE = 0;
private static final String TAG = "MainActivity";

private Messenger mService;

private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
Message msg = Message.obtain(null, SAY_HOLLE,0,0);
Bundle data = new Bundle();
data.putString("msg", "hello, this is client.");
msg.setData(data);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "onCreate");
Intent intent = new Intent(this, MessengerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onDestroy() {
unbindService(mConnection);
super.onDestroy();
Log.e(TAG, "onDestroy");
}
}

这样就完成了利用Messenger实现进程间通信的功能。如果需要实现服务端能够回应客户端,那么客户端就应该和服务端一样,需要新建一个Handler,并通过这个Handler新建一个新的Messenger,将这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数在服务端新建一个Messenger对象,发送Message类型的参数就可以回应客户端。

实现上述功能客户端需要添加的代码是:

private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler());

private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case TO_HOLLE:
Log.e(TAG, "receiver msg from Service:" + msg.getData().getString("reply"));
break;
default:
super.handleMessage(msg);
}
}
}


msg.replyTo = mGetReplyMessenger;


服务端需要添加的代码是:

Messenger client = msg.replyTo;
Message replyMessage = Message.obtain(null, TO_HOLLE);
Bundle bundle = new Bundle();
bundle.putString("reply", "嗯, 你的消息我已经收到, 稍后会回复你");
replyMessage.setData(bundle);
try {
client.send(replyMessage);
} catch (RemoteException e) {
e.printStackTrace();
}

服务端总的完整代码就是:

/**
* Created by su on 2017/10/26.
*/

public class MessengerService extends Service {

private static final int SAY_HOLLE = 0;
private static final int TO_HOLLE = 1;

private static final String TAG = "MessengerService";

private static class MessengerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case SAY_HOLLE:
Log.e(TAG, "receive msg from client:" + msg.getData().getString("msg"));
Messenger client = msg.replyTo; Message replyMessage = Message.obtain(null, TO_HOLLE); Bundle bundle = new Bundle(); bundle.putString("reply", "嗯, 你的消息我已经收到, 稍后会回复你"); replyMessage.setData(bundle); try { client.send(replyMessage); } catch (RemoteException e) { e.printStackTrace(); }
break;
default:
super.handleMessage(msg);

}
}
}

private final Messenger mMessenger = new Messenger(new MessengerHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();

}
}

客户端代码是:

public class MainActivity extends AppCompatActivity {
private static final int SAY_HOLLE = 0;
private static final int TO_HOLLE = 1;

private static final String TAG = "MainActivity";

private Messenger mService;
private Messenger mGetReplyMessenger = new Messenger(new MessengerHandler()); private static class MessengerHandler extends Handler{ @Override public void handleMessage(Message msg) { switch(msg.what){ case TO_HOLLE: Log.e(TAG, "receiver msg from Service:" + msg.getData().getString("reply")); break; default: super.handleMessage(msg); } } }

private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
Message msg = Message.obtain(null, SAY_HOLLE,0,0);
Bundle data = new Bundle();
data.putString("msg", "hello, this is client.");
msg.setData(data);
//
msg.replyTo = mGetReplyMessenger;
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "onCreate");
Intent intent = new Intent(this, MessengerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onDestroy() {
unbindService(mConnection);
super.onDestroy();
Log.e(TAG, "onDestroy");
}
}

最后在logcat观察打印输出的结果时,由于服务端和客户端在一个应用的不同进程,客户端在默认的包名进程下,这样不加设置的话只能看到客户端的log打印输出结果,如果要查看服务端的log打印结果,应该在log上设置过滤器,这样才能查看服务端的日志打印结果。如:



这样在logcat中观察服务端打印的信息就如下图所示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  messenger 解决方案