Android multi-process series
- Several basic problems of Android multi-process communication
- Binder for Android multiprocess
- Android multiprocess manual Binder class
- Android multiprocess Binder unbinding listener issues
- Accidental death and permissions verification for Android Multiprocess Binder
Messenger can also be used as a way of communicating with Multiple Android processes, building Messages to pass data between clients and servers
Using Messenger
The client sends messages to the server process through Messenger
- Build a server that runs in a separate process:
public class MessengerService extends Service {
private static final String TAG = "MessagerService"; /** * Handle messages from clients, Private static class MessengerHandler extends Handler {@override public void handleMessage(Message) message) { switch (message.what) {case MESSAGE_FROM_CLIENT:
Log.e(TAG, "receive message from client:" + message.getData().getString("msg"));
break;
default:
super.handleMessage(message);
break; Private final Messenger mMessenger = new Messenger(new MessengerHandler()); Nullable @override public IBinder onBind(Intent Intent) {// Return the Messenger object's Binder to the clientreturnmMessenger.getBinder(); }}Copy the code
- Register service, of course, in a different process
<service
android:name="com.xxq2dream.service.MessengerService"
android:process=":remote" />
Copy the code
- The client then creates the Messenger object by binding the binder returned by the server and sends messages to the server through this Messenger object
public class MessengerActivity extends AppCompatActivity {
private static final String TAG = "MessengerActivity";
private Messenger mService;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.e(TAG, "ServiceConnection-->"+ System.currentTimeMillis()); MService = new Messenger(iBinder); Message.obtain(null, MESSAGE_FROM_CLIENT); Bundle bundle = new Bundle(); bundle.putString("msg"."hello service,this is client"); message.setData(bundle); // Send a message to the server mservice.send (message); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { Log.e(TAG,"onServiceDisconnected-->binder died"); }}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_messenger); Intent = new Intent(this, messengerservice.class);bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {// unbindService unbindService(mConnection); super.onDestroy(); }}Copy the code
From the above experience, we can see that using Messenger to communicate across processes requires Message delivery, and Message can use the setData method to deliver complex data using bundles.
The replyTo parameter of Message is used by the server to reply a Message to the client
- Server Transformation
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case Constant.MESSAGE_FROM_CLIENT:
Log.e(TAG, "receive message from client:" + message.getData().getString("msg")); // Return a message to the Messenger client via Messenger = message.replyTo; Message MSG = message.obtain (null, constant.message_from_service); Bundle bundle = new Bundle(); bundle.putString("msg"."hello client, I have received your message!");
msg.setData(bundle);
try {
client.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(message);
break; }}}Copy the code
- The client transformation involves building a Messenger object with Handle and passing the Messenger object to the server using the replyTo parameter of Message when sending a Message to the server
/** * To build the client Messenger object, */ Private static class MessengerHandler extends Handler {@override public void handleMessage(Message) message) { switch (message.what) {case Constant.MESSAGE_FROM_SERVICE:
Log.e(TAG, "receive message from service:" + message.getData().getString("msg"));
break;
default:
super.handleMessage(message);
break; Private Messenger mClientMessenger = new Messenger(new MessengerHandler()); private ServiceConnection mConnection = newServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.e(TAG, "ServiceConnection-->" + System.currentTimeMillis());
mService = new Messenger(iBinder);
Message message = Message.obtain(null, MESSAGE_FROM_CLIENT);
Bundle bundle = new Bundle();
bundle.putString("msg"."hello service,this is client"); message.setData(bundle); // Pass the client Messenger object to the server message.replyTo = mClientMessenger; try { mService.send(message); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { Log.e(TAG,"onServiceDisconnected-->binder died"); }};Copy the code
conclusion
- Messager is used to pass messages. The only fields that can be used in a Message are WHAT, arg1, arg2, Bundle, and replyTo. Custom Parcelable objects cannot be transmitted through object fields
- The Bundle in Message supports multiple data types, and the replyTo field is used to transport Messager objects for communication between processes
- Messager processes messages from clients in a serial manner and is not suitable for large numbers of concurrent requests
- The Messager method can only pass messages and cannot call methods across processes
Welcome to pay attention to my wechat public number, looking forward to learning, communicating and growing together with you!Copy the code