IPC之Messenger
来源:互联网 发布:mac手机铃声 编辑:程序博客网 时间:2024/05/29 03:25
我们知道Service开启的方式有俩种:
- startService
- bindService
使用startService开启服务, 一般都不和Service进行交互,
而使用bindService开启服务,一般都需要和Service进行交互,因此,如果想获取Service,并和它进行交互,请使用bindService
使用bindService有如下几种情况
-1,service和client都属于同一个process
-2, service和client属于不同的process, 给service发送消息
-3, service和client属于不同的process, 需要调用service(其实是onBind()方法返回的ibinder对象)的多个方法
第一种方式,很简单,直接创建一个内部类继承自Binder, 然后在service的onBind()方法中返回此内部类的对象
第二种方式,我们可以使用Messenger的getBinder()对象作为onBind的返回值。
第三种方式,是采取aidl方式进行通信。
今天,我们只说第二种,分析第二种的原理:
首先,创建一个service,并且在AndroidManifest.xml里面配置,并加上android:process属性
public class MessagerService extends Service { public MessagerService() { } //创建一个handler private Handler ipcHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.e("LF", "msg.what : " + msg.what + ", msg.arg1 : " + msg.arg1); Log.e("LF", "handleMessage thread : " + Thread.currentThread() + ", process : " + Process.myPid()); } }; //使用ipcHandler构建一个Messenger对象 private Messenger messenger = new Messenger(ipcHandler); @Override public IBinder onBind(Intent intent) { Log.e("LF", "onBind pid : " + Process.myPid()); //将messenger中的binder返回。 return messenger.getBinder(); }}//在manifest中的配置, 加上process属性,就表示运行在不同的进程中 <service android:name=".MessagerService" android:process=".remoteMessenger" android:enabled="true" android:exported="true"> </service>
首先来看一下Messenger messenger = new Messenger(ipcHandler); 打开Messenger的源码,通过handler构造一个Messenger, 内部只是调用handler的getIMessenger()方法,将其返回值保存在mTarget成员变量。
public Messenger(Handler target) { mTarget = target.getIMessenger(); }
在来看一下onBind()方法中返回的messenger.getBinder()方法在Messenger类中的定义
public IBinder getBinder() { //它返回的是mTarget.asBinder对象 return mTarget.asBinder(); }
通过前面构造Messenger时,我们清楚mTarget是Handler中的getIMessenger()的返回值, 我们来看一下此方法
final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } }
从方法的定义可以看到getIMessenger()方法返回的是MessengerImpl对象,
private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); } }
MessengerImpl类是Handler类的内部类,它继承自IMessenger.Stub类,看到Stub,我们是不是想到了AIDL文件自动生成的内部类呀,Stub类是继承自Binder的,所以MessengerImpl是一个Binder对象。
我们也来看一下此IMessenger.java类
public interface IMessenger extends android.os.IInterface{ public static abstract class Stub extends android.os.Binder implements android.os.IMessenger { ...... public Stub() { this.attachInterface(this, DESCRIPTOR); } 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; } ......
和我们自己创建的aidl文件之后,系统给我们自动生成的一模一样, 因此我们在onBind()方法中返回的mTarget.asBinder() ,就等于handler.getIMessenger().asBinder() ,最后其实就是MessengerImpl, 它是Stub的子类。和我们自己创建aidl一样, 至此,服务端的代码分析完了, 我们接下来看一下客户端。
客户端的调用, 和正常的bindService一样,采取显示intent的方式,(android 5.0以上必须采取显示intent的方式开启服务, 否则会抛异常)
private Messenger mMessenger; ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { Log.e("LF", " iBinder : " + iBinder); //根据iBinder创建一个Messenger对象 mMessenger = new Messenger(iBinder); isConnection = true; try { iBinder.linkToDeath(new MyDeathRecipient(), 0); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName componentName) { } };//开启服务的代码 @Override public void onClick(View view) { switch (view.getId()) { //开启服务端的代码 case R.id.bindMessager: Intent messagerIntent = new Intent(this, MessagerService.class); this.bindService(messagerIntent, conn, BIND_AUTO_CREATE); break; case R.id.unBindMessager: //unbind service的代码 if (isConnection) { this.unbindService(conn); isConnection = false; } break; case R.id.invokeIPC: //调用服务端的代码 if (isConnection && mMessenger != null) { Message message = Message.obtain(); message.what = 10; message.arg1 = 21; try { mMessenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } } break; default: } }
当服务开启之后,我们在onServiceConnected()方法中可以获取到service端返回的iBinder对象。此iBinder对象在非IPC中,它就是MessengerImpl对象,如果在IPC中,那么此iBinder是BinderProxy, 它是一个代理。
public void onServiceConnected(ComponentName componentName, IBinder iBinder) { Log.e("LF", " iBinder : " + iBinder); mMessenger = new Messenger(iBinder); isConnection = true; try { iBinder.linkToDeath(new MyDeathRecipient(), 0); } catch (RemoteException e) { e.printStackTrace(); } }
我们来看一下new Messenger(iBinder) 这句话,底层做了啥?
public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }
从上述代码里面可以很清楚的看到,其实它就是我们之前使用aidl的写法,将IMessenger.Stub.asInterface返回的对象,赋值给mTarget对象
来看一下IMessenger.Stub 中asInterface()方法的定义
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); } //本地没有,就返回Stub.Proxy内部类对象 return new android.os.IMessenger.Stub.Proxy(obj);}
这里我们先不分析asInterface底层实现,只需要记住,如果是IPC,客户端获取到的是proxy.所以,这里mTarget是IMessenger.Stub的内部proxy
我们再来看一下mMessenger.send(message);这句底层实现
public void send(Message message) throws RemoteException { mTarget.send(message); }
其实就是调用mTarget的send。也就是调用proxy的send
@Override public void send(android.os.Message msg) throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();try { _data.writeInterfaceToken(DESCRIPTOR);if ((msg!=null)) { _data.writeInt(1); msg.writeToParcel(_data, 0);} else { _data.writeInt(0);}mRemote.transact(Stub.TRANSACTION_send, _data, null, android.os.IBinder.FLAG_ONEWAY);} finally { _data.recycle();}}static final int TRANSACTION_send = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
我们看到是调用mRemote的transact方法,mRemote对象是我们传入的iBinder对象,其实最终会调用Stub的onTransact方法, 然后在onTransact方法里面进行switch根据传入的TRANSACTION_send 判断,最后调用的是MessengerImpl的send方法
public void send(Message msg) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); }
最终就会走正常的handler 的流程。
从以上的分析,可以看出,Messenger底层也是使用AIDL来实现的。在服务端通过Handler来构建一个MessengerImpl 的Bindler对象,将此Bindler对象通过onBind()方法返回, 在客户端,以bindService开启服务之后, 根据服务端传回来的iBinder对象创建一个Messenger对象, 这样客户端中的Messenger对象,就获取到了service端的IMessenger的代理(IPC, 非IPC是MessengerImpl对象)。这样,客户端和服务端,就可以通过Messenger的send方法进行通信了。
当然使用Messenger也可以从client端向service端的子线程发送handler消息, 只需要在service端构建Messenger的时候,传入一个带子线程Looper对象的Handler即可。
public class MessagerService extends Service { public MessagerService() { } private Handler ipcHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.e("LF", "msg.what : " + msg.what + ", msg.arg1 : " + msg.arg1); Log.e("LF", "handleMessage thread : " + Thread.currentThread() + ", process : " + Process.myPid()); } }; private class MyAsyncHandler extends Handler { MyAsyncHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); Log.e("LF", "msg.what : " + msg.what + ", msg.arg1 : " + msg.arg1); Log.e("LF", "handleMessage thread : " + Thread.currentThread() + ", process : " + Process.myPid()); } } private Looper mHandlerLooper; private MyAsyncHandler myAsyncHandler; private Messenger mAsyncMessenger; @Override public void onCreate() { super.onCreate(); //构建一个HandlerThread ,HandlerThread内部开启一个子线程,并且创建一个Looper,并进行loop循环。 HandlerThread handlerThread = new HandlerThread("MessengerHandlerThread"); handlerThread.start(); this.mHandlerLooper = handlerThread.getLooper(); this.myAsyncHandler = new MyAsyncHandler(mHandlerLooper); //根据此Handler去构建一个Messenger对象 mAsyncMessenger = new Messenger(myAsyncHandler); } private Messenger messenger = new Messenger(ipcHandler); @Override public IBinder onBind(Intent intent) { return mAsyncMessenger.getBinder(); } @Override public void onDestroy() { super.onDestroy(); this.mHandlerLooper.quit();//自己开启的loop一定要记得退出 }}
唯一注意一点的是,自己创建的Looper一定要记得调用quit或者quitSafe退出,否则,线程会一直存在。
如果服务端需要给客户端回应,那么在client端也构建一个Messenger对象,将Messenger对象赋值给message的replyTo,发送给service端,
Messenger 的内部是使用handler来处理消息的,所以,它是一个串行的过程。如果要处理并发的请求,或者跨进程调用service端的方法,请使用AIDL
- Android IPC之Messenger
- Android IPC 之Messenger
- IPC机制之Messenger
- IPC之Messenger
- IPC之Messenger
- IPC之Messenger
- Android IPC之 Messenger
- Android IPC之Messenger
- Android IPC之Messenger解析
- IPC机制之AIDL、Messenger
- Android IPC之Messenger浅谈
- Android IPC之Messenger介绍
- Android IPC之Messenger浅谈
- IPC机制之Messenger示例
- android加深笔记--IPC通信之Messenger
- Android笔记之IPC机制:Messenger
- Android进程间通信(IPC)之Messenger
- android ipc机制之Messenger的使用
- 【框架基础】:Java反射机制详解(二)
- svn提交时报错: The working copy needs to be upgraded svn: Working copy 'E:\java\MyEclipse\Workspaces\fram
- 第二期 AOSP 环境搭建、下载和编译 《手机就是开发板》
- Android之数据统计TalkingData集成
- 【Android】导入第三方库时,关于so文件的一些思考
- IPC之Messenger
- NULL, '\0',0 '0'的区别
- fiddler4 测试Web接口
- 前端编程中,如何消除浏览器缓存
- Unity3D Shader 新手教程(1/6)
- codeforces round 345 div2 Image Interview 贪心 + 二分
- 请不要做一个浮躁的嵌入式工程师
- C# 第14章 上机3,4,5
- Fizz Buzz 问题