前言
搞网络管理 ConnectivityService 的时候发现里面用了很多Asynchannel。查了一下看了一下源码发现它是messenger封装的,而messenger又是基于aidl 的,所以这里在写Asynchannel 之前用一篇文章来介绍一下Messenger 。
Messenger 与AIDL 的区别
1、Messenger适合传递数据少,数据量小的情况,直接发送message或者携带bundle,AIDL适合数据多,数据量大的情况
2、Messenger 是异步的,因为它在实现的时候源码里面AIDL 接口的类型是oneway 参数。
Messenger 的原理分析
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
1、构造函数里面需要传入一个Handler,handler 的getIMessenger() 实际上是通过 MessengerImpl 获取messenger 的对象。
MessengerImpl 继承 IMessenger.Stub类,是messenger binder 跨进程的服务端。
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);
}
}
2、在Messenger 的客户端可以通过IBinder 接口获取服务端的messenger。
/**
* 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);
}
3、发送message 消息 ,可以在message里面携带Bundle信息
/**
* 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);
}
4.流程图
这里盗一张图充个门面。其中补充一下Messenger 的binder 跨进程实现是 IMessenger.Stub.asInterface 为客户端,服务端是 extends IMessenger.Stub 的类,比如 Handler 里面 MessengerImpl 就是messenger 的服务端实现类。
Messenger 的使用可以是单向的客户端向服务端发送消息,也可以是服务端收到客户端消息后message.replyTo.send(replyMsg) 回复消息,message的replyTo 实际上 是获取了一个messenger对象。这里是客户端 发消息的message通过replyTo 参数里面传一个 messenger 对象尽量msg.replyTo = clientMessenger就会获取到服务端发送过来的Messenger 对象。
重点说完了,贴一个demo 源码吧 。。。
客户端:
package com.tsp.asyncchanneldemo.messenger;
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.Looper;
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 androidx.appcompat.app.AppCompatActivity;
import com.tsp.asyncchanneldemo.R;
public class MessengerClientActivity extends AppCompatActivity {
private static final String TAG=MessengerClientActivity.class.getSimpleName();
private Button mButton;
public static final int FROM_SERVER = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_messenger_activity);
//启动服务
startService();
//绑定服务
bindService();
mButton = (Button) findViewById(R.id.button);
mButton.setEnabled(false);
//点击按键后,利用Messenger向Service发送消息
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mMessenger != null) {
try {
Message msg = Message.obtain();
msg.what = 1;
Bundle data = new Bundle();
data.putString("msg", "I am from the client.");
msg.setData(data);
//message replyto from server
msg.replyTo = clientMessenger;
mMessenger.send(msg);
} catch (RemoteException e) {
}
}
}
});
}
//client messenger handler
private Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case FROM_SERVER:
Log.d(TAG,"get msg from server");
Log.e(TAG, msg.getData().getString("reply"));
break;
default:
break;
}
}
};
private Messenger clientMessenger = new Messenger(handler);
@Override
public void onDestroy() {
super.onDestroy();
unBindService();
stopService();
}
private Intent mIntent;
private void startService() {
mIntent = new Intent(this, MessengerService.class);
this.startService(mIntent);
}
private ServiceConnection mServiceConnection;
private void bindService() {
mServiceConnection = new LocalServiceConnection();
this.bindService(mIntent, mServiceConnection, BIND_AUTO_CREATE);
}
Messenger mMessenger;
private class LocalServiceConnection implements android.content.ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//绑定服务后,获得Messenger并激活Button
mMessenger = new Messenger(service);
mButton.setEnabled(true);
}
@Override
public void onServiceDisconnected(ComponentName name) {
mButton.setEnabled(false);
}
}
private void stopService() {
stopService(mIntent);
}
private void unBindService() {
unbindService(mServiceConnection);
}
}
服务端:
package com.tsp.asyncchanneldemo.messenger;
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;
import androidx.annotation.Nullable;
public class MessengerService extends Service {
private static final String TAG = "MessengerService";
/**
* 处理来自客户端的消息,并用于构建Messenger
*/
private static class MessengerHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case 1:
Log.e(TAG, "receive message from client:" + message.getData().getString("msg"));
//回复消息给客户端
Message replyMsg = Message.obtain();
replyMsg.what = 1;
Bundle bundle = new Bundle();
bundle.putString("reply", "听到你的消息了,请说点正经的");
replyMsg.setData(bundle);
try {
message.replyTo.send(replyMsg); //回信
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(message);
break;
}
}
}
/**
* 构建Messenger对象
*/
private final Messenger mMessenger = new Messenger(new MessengerHandler());
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG,"onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
//将Messenger对象的Binder返回给客户端
return mMessenger.getBinder();
}
}
AndroidManifest 文件里面服务端加上 process 属性
android:process=":remote"
写到这里就O 了,大概就是这样吧,下一篇写Asychannel。