注册

Android IPC 之 Messenger

绑定服务(Bound Services)概述


绑定服务是client-server接口中的服务器。它允许组件(例如活动)绑定到服务、发送请求、接收响应和执行进程间通信(IPC)。 绑定服务通常仅在它为另一个应用程序组件提供服务时才存在,并且不会无限期地在后台运行


💥 基础知识


绑定服务是 Service 类的实现,它允许其他应用程序绑定到它并与之交互。 要为服务提供绑定,你必须实现 onBind() 回调方法。 此方法返回一个 IBinder 对象,该对象定义了客户端可用于与服务交互的编程接口。


🔥 Messenger


💥 概述


一提到IPC 很多人的反应都是 AIDL,其实如果仅仅是多进程单线程,那么你可以使用 Messenger 为你的服务提供接口。


使用 Messenger 比使用 AIDL 更简单,因为 Messenger 会将所有对服务的调用排入队列


对于大多数应用程序,该服务不需要执行多线程,因此使用 Messenger 允许该服务一次处理一个调用。如果你的 服务多线程很重要,那你就要用到ALDL了。


💥 使用 Messenger 步骤




  • 1、该 Service 实现了一个 Handler,该 Handler 接收来自客户端的每次调用的回调。




  • 2、该服务使用 Handler 创建一个 Messenger 对象(它是对 Handler 的引用)。




  • 3、Messenger 创建一个 IBinder,该服务从 onBind() 返回给客户端。




  • 4、客户端使用 IBinder 来实例化 Messenger(引用服务的Handler),客户端使用 Handler 来向服务发送 Message 对象。




  • 5、服务在其 Handler 的 handleMessage() 中接收每个消息。




💥 实例(Client到Server数据传递)


🌀 MessengerService.java


public class MessengerService extends Service {
public static final int MSG_SAY_HELLO = 0;
//让客户端向IncomingHandler发送消息。
Messenger messenger = null;

//当绑定到服务时,我们向我们的Messenger返回一个接口,用于向服务发送消息。
public IBinder onBind(Intent intent) {
MLog.e("MessengerService:onBind");
//创建 Messenger 对象(对 Handler 的引用)
messenger = new Messenger(new IncomingHander(this));
//返回支持此Messenger的IBinder。
return messenger.getBinder();
}
//实现了一个 Handler
static class IncomingHander extends Handler {
private Context appliacationContext;
public IncomingHander(Context context) {
appliacationContext = context.getApplicationContext();
}

@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MSG_SAY_HELLO:
Bundle bundle = msg.getData();
String string = bundle.getString("name");
//处理来自客户端的消息
MLog.e("handleMessage:来自Acitvity的"+string);
break;
case 1:

break;
default:
super.handleMessage(msg);
}
}
}
}

🌀 AndroidMainfest.xml


        <service android:name=".ipc.MessengerService"
android:process="com.scc.ipc.messengerservice"
android:exported="true"
android:enabled="true"/>

使用 android:process 属性 创建不同进程。


🌀 MainActivity.class


public class MainActivity extends ActivityBase implements View.OnClickListener {
Messenger mService = null;
Messenger messenger = null;
private boolean bound;
private ViewStub v_stud;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}

ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//从原始 IBinder 创建一个 Messenger,该 IBinder 之前已使用 getBinder 检索到。
mService = new Messenger(service);
bound = true;
}

@Override
public void onServiceDisconnected(ComponentName name) {
bound = false;
}
};

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind_service:
bindService(new Intent(MainActivity.this, MessengerService.class), connection, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_send_msg:
Message message = Message.obtain(null, MessengerService.MSG_SAY_HELLO);
Bundle bundle = new Bundle();
bundle.putString("name","Scc");
message.setData(bundle);
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;

}
}
@Override
protected void onStop() {
super.onStop();
if (bound) {
unbindService(connection);
bound = false;
}
}
}

🌀 运行效果如下



两个进程也存在着,也完成了进程间的通信,并把数据传递过去了。


💥 实例(Server将数据传回Client)


我不仅想将消息传递给 Server ,还想让 Server 将数据处理后传会Client。


🌀 MessengerService.java


public class MessengerService extends Service {
/** 用于显示和隐藏我们的通知。 */
ArrayList<Messenger> mClients = new ArrayList<Messenger>();
/** 保存客户端设置的最后一个值。 */
int mValue = 0;

/**
* 数组中添加 Messenger (来自客户端)。
* Message 的 replyTo 字段必须是应该发送回调的客户端的 Messenger。
*/
public static final int MSG_REGISTER_CLIENT = 1;

/**
* 数组中删除 Messenger (来自客户端)。
* Message 的 replyTo 字段必须是之前用 MSG_REGISTER_CLIENT 给出的客户端的 Messenger。
*/
public static final int MSG_UNREGISTER_CLIENT = 2;
/**
* 用于设置新值。
* 这可以发送到服务以提供新值,并将由服务发送给具有新值的任何注册客户端。
*/
public static final int MSG_SET_VALUE = 3;
//让客户端向IncomingHandler发送消息。
Messenger messenger = null;

//当绑定到服务时,我们向我们的Messenger返回一个接口,用于向服务发送消息。
public IBinder onBind(Intent intent) {
MLog.e("MessengerService-onBind");
//创建 Messenger 对象(对 Handler 的引用)
messenger = new Messenger(new IncomingHander(this));
//返回支持此Messenger的IBinder。
return messenger.getBinder();
}
//实现了一个 Handler
class IncomingHander extends Handler {
private Context appliacationContext;
public IncomingHander(Context context) {
appliacationContext = context.getApplicationContext();
}

@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
case MSG_SET_VALUE:
mValue = msg.arg1;
for (int i=mClients.size()-1; i>=0; i--) {
try {
mClients.get(i).send(Message.obtain(null,
MSG_SET_VALUE, mValue, 0));
} catch (RemoteException e) {
// 客户端没了。 从列表中删除它;
//从后往前安全,从前往后遍历数组越界。
mClients.remove(i);
}
}
default:
super.handleMessage(msg);
}
}
}
}

🌀 MainActivity.java


public class MainActivity extends ActivityBase implements View.OnClickListener {
Messenger mService = null;
Messenger messenger = null;
private boolean bound;
private ViewStub v_stud;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}

ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//从原始 IBinder 创建一个 Messenger,该 IBinder 之前已使用 getBinder 检索到。
mService = new Messenger(service);
bound = true;
}

@Override
public void onServiceDisconnected(ComponentName name) {
bound = false;
}
};
static class ReturnHander extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MessengerService.MSG_SET_VALUE:
//我要起飞:此处处理
MLog.e("Received from service: " + msg.arg1);
break;
default:
super.handleMessage(msg);
}
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind_service:
bindService(new Intent(MainActivity.this, MessengerService.class), connection, Context.BIND_AUTO_CREATE);
break;
case R.id.btn_send_msg:
try {
mMessenger = new Messenger(new ReturnHander());
Message msg = Message.obtain(null,
MessengerService.MSG_REGISTER_CLIENT);
msg.replyTo = mMessenger;
//先发一则消息添加Messenger:msg.replyTo = mMessenger;
mService.send(msg);

// Give it some value as an example.
msg = Message.obtain(null,
MessengerService.MSG_SET_VALUE, this.hashCode(), 0);
//传入的arg1值:this.hashCode()
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
break;

}
}
@Override
protected void onStop() {
super.onStop();
if (bound) {
unbindService(connection);
bound = false;
}
}
}

🌀 运行效果如下



我们在MainActivity 的 Handler.sendMessger()中接收到了来自 MesengerService 的消息 。


本次 Messenger 进程间通信齐活,这只是个简单的Demo。最后咱们看一波源码。


🔥 Messenger 源码


Messenger.java


public final class Messenger implements Parcelable {
private final IMessenger mTarget;
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
public IBinder getBinder() {
return mTarget.asBinder();
}
...
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
}

然后你会发现 只要代码还是在 IMessenger 里面,咱们去找找。


IMessenger.aidl


package android.os;

import android.os.Message;

/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}

new Messenger(Handler handelr)


这里其实是用Handler 调用 getIMessenger() 。咱们去Handler.class里面转转。


    @UnsupportedAppUsage
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
//创建了Messenger实现类
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
//Messenger调用send()方法,通过Handler发送消息。
//然后在服务端通过Handler的handleMessge(msg)接收这个消息。
Handler.this.sendMessage(msg);
}
}

new Messenger(IBinder target)


package android.os;
/** @hide */
public interface IMessenger extends android.os.IInterface
{
/** Default implementation for IMessenger. */
public static class Default implements android.os.IMessenger
{
@Override public void send(android.os.Message msg) throws android.os.RemoteException
{
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements android.os.IMessenger
{
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.os.IMessenger interface,
* generating a proxy if needed.
*/
public static android.os.IMessenger asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//判断是否在同一进程。
if (((iin!=null)&&(iin instanceof android.os.IMessenger))) {
//同一进程
return ((android.os.IMessenger)iin);
}
//代理对象
return new android.os.IMessenger.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
...
}
public void send(android.os.Message msg) throws android.os.RemoteException;
}

看了上面代码你会发现这不就是个aidl吗? 什么是aidl,咱们下一篇继续讲到。


作者:Android帅次
链接:https://juejin.cn/post/7022881022438015007
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册