一、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 {
@Override
protected 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">
<TextView
android: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() {
@Override
public 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);
@Override
public IBinder onBind(Intent intent) {
return mServerMessenger.getBinder();//3、向客户端返回服务端的Binder
}
@Override
public 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">
<application
android: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" -->
<service
android: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";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
Messenger mServerMessenger = null;
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mServerMessenger = new Messenger(service);
Log.e(TAG, "onServiceConnected: bind server successfully");
}
@Override
public void onServiceDisconnected(ComponentName name) {//注:unbindService不会调用此方法
mServerMessenger = null;
Log.e(TAG, "onServiceDisconnected: disconnected to server");
}
};
//3、绑定服务端并在回调方法onServiceConnected中保存下服务端的Messenger
public 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() {
@Override
public 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: ");
}
@Override
protected 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">
<application
android: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">
<Button
android:id="@+id/bind"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="bind"
android:onClick="bind"
/>
<Button
android: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、执行效果图如下。
参考文章