一、Messenger是Google为我们封装好的简洁版的AIDL,当面对少量的并发进程间通信更适用。而且不用考虑线程同步问题。使用场景:少量的一对多的串行进程间通信,支持实时通信,使用比较简单,不支持直接调用服务端的方法。
二、android的屏幕截屏功能就是用到这个Messenger。
三、下面让我们实例学习吧。
1、服务器端代码
1.1 源码大概的界面
1.2 src\main\java\com\giada\messenger_server\MainActivity.java
package com.giada.messenger_server;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}
}
1.3 src\main\res\layout\activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
1.4 src\main\java\com\giada\messenger_server\GDService.java
package com.giada.messenger_server;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
public class GDService extends Service {private static final String TAG = "BINDERMESSENGERDOME";//1、用于接收客户端发送过来的消息Handler mServerHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 1://获取来自客户端的消息Bundle data = msg.getData();String clientMsg = data.getString("clientMsg");Log.e(TAG, "handleMessage: message from client:clientMsg=" + clientMsg);// 向客户端回复消息Messenger clientMessenger = msg.replyTo; //获取到客户端的 Messenger,这里可以保存为全局变量,以后就不用每次都去获取了Message toClientMsg = Message.obtain();toClientMsg.what=1;Bundle bundle = new Bundle();bundle.putString("serverMsg", "I am server,recevied your message!");toClientMsg.setData(bundle);try {clientMessenger.send(toClientMsg);//回复客户端} catch (RemoteException e) {e.printStackTrace();}break;default:super.handleMessage(msg);break;}}};//2、使用Handler创建Messenger。Messenger mServerMessenger = new Messenger(mServerHandler);@Overridepublic IBinder onBind(Intent intent) {return mServerMessenger.getBinder();//3、向客户端返回服务端的Binder}@Overridepublic void onDestroy() {super.onDestroy();Log.e(TAG, "onDestroy: MyServerService" );}
}
1.5 src\main\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.giada.messenger_server"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Messenger_server"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><!--注:服务端的包名为:com.giada.messenger_server,客户端绑定Service的时候是使用程序的包名,不是使用MyServerService类的包名 android:process=":messenger" --><serviceandroid:name=".GDService"android:enabled="true"android:exported="true"android:process=":mesengerserver"><intent-filter><action android:name="com.giada.messenger_server.server.action"/></intent-filter></service></application></manifest>
2、客户端代码
2.1 源码大概的界面
2.2 src\main\java\com\giada\messenger_client\MainActivity.java
package com.giada.messenger_client;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {private static final String TAG = "BINDERMESSENGERDOME";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}Messenger mServerMessenger = null;ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mServerMessenger = new Messenger(service);Log.e(TAG, "onServiceConnected: bind server successfully");}@Overridepublic void onServiceDisconnected(ComponentName name) {//注:unbindService不会调用此方法mServerMessenger = null;Log.e(TAG, "onServiceDisconnected: disconnected to server");}};//3、绑定服务端并在回调方法onServiceConnected中保存下服务端的Messengerpublic void bind(View view) {Intent intent = new Intent();ComponentName serviceComponent = ComponentName.unflattenFromString("com.giada.messenger_server/com.giada.messenger_server.GDService");intent.setComponent(serviceComponent);boolean bindService = bindService(intent, mConnection, BIND_AUTO_CREATE);Log.i(TAG, "bind: bindService=" + bindService);}//1、创建一个Handler用于接收服务端发送过来的消息Handler mClientHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 1://获取来自服务端的消息Bundle data = msg.getData();String serverMsg = data.getString("serverMsg");Log.e(TAG, "handleMessage: message for server:serverMsg=" + serverMsg);break;default:super.handleMessage(msg);break;}}};//2、构建一个客户端的Messenger,方便服务端使用Messenger mClientMessenger = new Messenger(mClientHandler);//4、使用服务端的Messenger发送消息给服务端,并携带上客户端的Messenger。public void sendMessageToServer(View view) {if (mServerMessenger == null) return;// 向服务端发送消息Message toServerMsg = Message.obtain();toServerMsg.what = 1;toServerMsg.replyTo = mClientMessenger;//将客户端的Messenger携带上,服务端可以用来回复客户端的消息Bundle bundle = new Bundle();bundle.putString("clientMsg", "hello,server ^_^");toServerMsg.setData(bundle);try {mServerMessenger.send(toServerMsg);//使用服务端的Messenger发送消息给服务端Log.e(TAG, "sendMessageToServer: ");} catch (RemoteException e) {e.printStackTrace();}}public void unBind(View view) {if (mServerMessenger != null) {unbindService(mConnection);mServerMessenger = null;}Log.e(TAG, "unBind: ");}@Overrideprotected void onDestroy() {super.onDestroy();unBind(null);}
}
2.3 src\main\AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.giada.messenger_client"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Messenger_client"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application><!--<queries><package android:name="com.giada.messenger_server" /></queries>--><queries><package android:name="com.giada.messenger_server" /></queries>
</manifest>
2.4 src\main\res\layout\activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="10dp"android:paddingLeft="10dp"android:paddingRight="10dp"android:paddingTop="10dp"android:background="@color/black"tools:context=".MainActivity"><Buttonandroid:id="@+id/bind"android:layout_width="100dp"android:layout_height="100dp"android:text="bind"android:onClick="bind"/><Buttonandroid:id="@+id/send"android:layout_below="@id/bind"android:layout_width="100dp"android:layout_height="100dp"android:text="send"android:onClick="sendMessageToServer"/>
</RelativeLayout>
3、在机器上运行这两个app
4、执行效果图如下。
参考文章
Android 的进程间通信 Binder——Messenger的入门使用 - 简书