1.概述
项目中常用到的进程间通信更多是用AIDL,在前阵子复习的时候才了解还有 Messenger 这种方法。既然要学习就记录下,以后要用的时候才能快速的掌握。
Messenger 是一种轻量级的IPC方案,它的底层实现是AIDL,可以在不同进程中传递 Message 对象,它一次只处理一个请求,在服务端不需要考虑线程同步的问题,服务端不存在并发执行的情况。
2. Messenger的构造方法
Public constructors | |
---|---|
Messenger(Handler target) Create a new Messenger pointing to the given Handler. | |
Messenger(IBinder target) Create a Messenger from a raw IBinder, which had previously been retrieved with |
3. Messenger 使用
3.1 客户端步骤:
3.1.1 创建一个handler对象,并实现 handleMessage() 方法,用户接收客户端的消息。
3.1.2 创建Messenger ,封装handler。
3.1.3 用Messenger的 getBinder() 方法获取一个IBinder对象,通过 onBind 返回给客户端。
服务端的Service:
package cn.zzw.messenger.server;
import android.app.Service;
import android.content.Intent;
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 MessengerService extends Service {
private static final String TAG = "MessengerService";
private MessengerHandler mHandler = new MessengerHandler();
private Messenger mMessenger = new Messenger(mHandler);
private static final int MSG_SUM = 10086;
private class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
if(msg.what==MSG_SUM)
{
Log.e(TAG,"handleMessage");
try {
int arg1 = msg.arg1;
int arg2=msg.arg2;
Message msgToClient=Message.obtain(msg);
msgToClient.arg1=arg1+arg2;
msg.replyTo.send(msgToClient);
} catch (RemoteException e) {
}
}
}
}
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
@Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacksAndMessages(null);
}
}
3.2 客户端步骤:
3.2.1 在 Activity 中绑定服务。
3.2.2 创建ServiceConnection并在其中使用 IBinder 将 Messenger实例化
3.2.3 使用Messenger向服务端发送消息
客户端主要代码:
package cn.zzw.messenger.client;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
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;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MessengerClient";
private TextView mTv;
private Messenger mService;
private static final int MSG_SUM = 10086;
private MessengerHandler mHandler = new MessengerHandler();
private Messenger mMessenger = new Messenger(mHandler);
private class MessengerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
if(msg.what==MSG_SUM)
{
Log.e(TAG,"handleMessage");
int arg1 = msg.arg1;
Log.e(TAG,"handleMessage:"+arg1);
Toast.makeText(MainActivity.this,"The Result is "+arg1,Toast.LENGTH_SHORT).show();
}
}
}
private ServiceConnection conn=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//获取服务端关联的Messenger对象
mService = new Messenger(iBinder);
Log.e(TAG,"onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e(TAG,"onServiceDisconnected");
mService=null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindToServserService();
mTv = findViewById(R.id.mTv);
findViewById(R.id.mBtn_cal).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Message msg = Message.obtain(null, MSG_SUM, 10, 500);
msg.replyTo = mMessenger;
if(null!=mService)
{
//往服务端发送消息
try {
Log.e(TAG,"mService.send");
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
/*
* 绑定服务端的Service
*/
private void bindToServserService() {
Intent intent=new Intent();
intent.setPackage("cn.zzw.messenger.server");
intent.setAction("CN.ZZW.MESSENGER.SERVER");
bindService(intent,conn,BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
mHandler.removeCallbacksAndMessages(null);
}
}
4. 运行结果
client端的log:
E/MessengerClient: mService.send
E/MessengerClient: mService.send
handleMessage
handleMessage:510
E/MessengerClient: handleMessage
handleMessage:510
Server端的log:
E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage
5.原理
先看下 Messenger 的源码,代码行数非常少:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/Messenger.java
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os;
/**
* Reference to a Handler, which others can use to send messages to it.
* This allows for the implementation of message-based communication across
* processes, by creating a Messenger pointing to a Handler in one process,
* and handing that Messenger to another process.
*
* <p>Note: the implementation underneath is just a simple wrapper around
* a {@link Binder} that is used to perform the communication. This means
* semantically you should treat it as such: this class does not impact process
* lifecycle management (you must be using some higher-level component to tell
* the system that your process needs to continue running), the connection will
* break if your process goes away for any reason, etc.</p>
*/
public final class Messenger implements Parcelable {
private final IMessenger mTarget;
/**
* Create a new Messenger pointing to the given Handler. Any Message
* objects sent through this Messenger will appear in the Handler as if
* {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
* been called directly.
*
* @param target The Handler that will receive sent messages.
*/
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
/**
* Send a Message to this Messenger's Handler.
*
* @param message The Message to send. Usually retrieved through
* {@link Message#obtain() Message.obtain()}.
*
* @throws RemoteException Throws DeadObjectException if the target
* Handler no longer exists.
*/
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
/**
* Retrieve the IBinder that this Messenger is using to communicate with
* its associated Handler.
*
* @return Returns the IBinder backing this Messenger.
*/
public IBinder getBinder() {
return mTarget.asBinder();
}
/**
* Comparison operator on two Messenger objects, such that true
* is returned then they both point to the same Handler.
*/
public boolean equals(Object otherObj) {
if (otherObj == null) {
return false;
}
try {
return mTarget.asBinder().equals(((Messenger)otherObj)
.mTarget.asBinder());
} catch (ClassCastException e) {
}
return false;
}
public int hashCode() {
return mTarget.asBinder().hashCode();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeStrongBinder(mTarget.asBinder());
}
public static final Parcelable.Creator<Messenger> CREATOR
= new Parcelable.Creator<Messenger>() {
public Messenger createFromParcel(Parcel in) {
IBinder target = in.readStrongBinder();
return target != null ? new Messenger(target) : null;
}
public Messenger[] newArray(int size) {
return new Messenger[size];
}
};
/**
* Convenience function for writing either a Messenger or null pointer to
* a Parcel. You must use this with {@link #readMessengerOrNullFromParcel}
* for later reading it.
*
* @param messenger The Messenger to write, or null.
* @param out Where to write the Messenger.
*/
public static void writeMessengerOrNullToParcel(Messenger messenger,
Parcel out) {
out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder()
: null);
}
/**
* Convenience function for reading either a Messenger or null pointer from
* a Parcel. You must have previously written the Messenger with
* {@link #writeMessengerOrNullToParcel}.
*
* @param in The Parcel containing the written Messenger.
*
* @return Returns the Messenger read from the Parcel, or null if null had
* been written.
*/
public static Messenger readMessengerOrNullFromParcel(Parcel in) {
IBinder b = in.readStrongBinder();
return b != null ? new Messenger(b) : null;
}
/**
* Create a Messenger from a raw IBinder, which had previously been
* retrieved with {@link #getBinder}.
*
* @param target The IBinder this Messenger should communicate with.
*/
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
}
这时候我们在回头看两个构造方法:
1. public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
2. public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
两个构造方法内部都是初始化对象 mTarget:
private final IMessenger mTarget;
再看看 IMessenger,是一个AIDL文件:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/IMessenger.aidl
/* //device/java/android/android/app/IActivityPendingResult.aidl
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}
在看看Handler 中的部分代码:
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
private final class MessengerImpl extends IMessenger.Stub {
public void send(Message msg) {
msg.sendingUid = Binder.getCallingUid();
Handler.this.sendMessage(msg);
}
}
从以上代码,可以看出Messenger又跟Binder联系起来了。 最终还是AIDL文件来完成的,只不过Messenger进行了深度的封装AIDL,使用起来更简单。
最后,附上文中的示例代码:https://download.csdn.net/download/zzw0221/11260381
参考:
https://blog.csdn.net/hzw2017/article/details/81090319
https://www.jianshu.com/p/48e212d1fde4