AIDL 的理解&源码分析
2016-01-26 16:59
525 查看
aidl通讯试所有的对象都得实现Parcelable 接口
onTransact() Binder 驱动执行完毕时需要回调的方法
Proxy 移动端IPC通讯的时候,消息都是通过Binder 进行传递的。
这个代理可以理解为:IPC机制中,Android代码 跟底层对应IPC的Binder驱动 之间进行通讯时的代理
asInterface() 查询本地所有的aidl 接口,判断该Binder对象是否为一个本地的 Binder引用
然后bindService的时候,需要传递一个 ServiceConnection的内部类实现,在ServiceConnection内部类实现中
bindService(intent, conn, BIND_AUTO_CREATE);
然后在客户端跟服务端交互的时候,我们可以通过看 aidl对应系统生成的java类中的描述,来撸清楚来龙去脉
ServiceManager 可以得到android系统的各个 ServiceManger对象,而每一个ServiceManger对象,又持有着各自对应的Binder 引用。
所以说,ServiceManager是Binder 驱动的一个引子,在IPC中 是客户端和服务端进行通信的媒介
onTransact() Binder 驱动执行完毕时需要回调的方法
Proxy 移动端IPC通讯的时候,消息都是通过Binder 进行传递的。
这个代理可以理解为:IPC机制中,Android代码 跟底层对应IPC的Binder驱动 之间进行通讯时的代理
asInterface() 查询本地所有的aidl 接口,判断该Binder对象是否为一个本地的 Binder引用
然后bindService的时候,需要传递一个 ServiceConnection的内部类实现,在ServiceConnection内部类实现中
bindService(intent, conn, BIND_AUTO_CREATE);
ServiceConnection conn=new ServiceConnection() { //aidl链接失败回调 @Override public void onServiceDisconnected(ComponentName name) { } //aidl连接成功回调 @Override public void onServiceConnected(ComponentName name, IBinder service) { //在系统内部将执行一下逻辑行为 /*public static com.aidl.lxcay.MyAidlInterface asInterface(android.os.IBinder obj) { * if ((obj == null)) { * return null; * } * 查询本地所有的aidl 的描述,判断该Binder对象是否为一个本地的 Binder引用 * android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); * if (((iin != null) && (iin instanceof com.aidl.lxcay.MyAidlInterface))) { * 返回定义好的代理接口 * return ((com.aidl.lxcay.MyAidlInterface) iin); * } * 返回默认代理 * return new com.aidl.lxcay.MyAidlInterface.Stub.Proxy(obj); * } */ //这个localInterface 就是aidl里面规定好的接口引用,即Binder 引用 localInterface = Stub.asInterface(service); //在客户端可以通过点击事件执行这个引用里对应的函数,如果执行成功,会在相应的Service里面执行相应的 函数; //下面给出一个demo } }; eg: //客户端 public void click(View v) throws RemoteException{ Log.i(TAG, localInterface.login("24", 24)+""); Log.i(TAG, localInterface.sayHello(new Person("lxcay", 24))+""); } //服务端 public class MyServices extends Service { @Override public IBinder onBind(Intent intent) { return new MyBind(); } // class MyBind 继承 Stub接口,为什么会重写一下2个回调方法,是因为在aidl文件对应的java代码里面有这句代码 /* * public static abstract class Stub extends android.os.Binder implements com.aidl.lxcay.MyAidlInterface {} * 在我自己定义的接口描述文件里面就有 * interface MyAidlInterface { * boolean login(String name,int age); * String sayHello(in Person p); * } */ class MyBind extends Stub{ @Override public boolean login(String name, int age) throws RemoteException { return !name.equals(age); } @Override public String sayHello(Person p) throws RemoteException { return "lxcay hello world, hello aidl~"; } } }
然后在客户端跟服务端交互的时候,我们可以通过看 aidl对应系统生成的java类中的描述,来撸清楚来龙去脉
/* * This file is auto-generated. DO NOT MODIFY. * Original file: D:\\SCode\\SogouGameSDKSample\\src\\com\\intfs\\MyAidlInterface.aidl */ package com.aidl.lxcay; public interface MyAidlInterface extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.aidl.lxcay.MyAidlInterface { private static final java.lang.String DESCRIPTOR = "com.aidl.lxcay.MyAidlInterface"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.aidl.lxcay.MyAidlInterface interface, * generating a proxy if needed. */ public static com.aidl.lxcay.MyAidlInterface asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.aidl.lxcay.MyAidlInterface))) { return ((com.aidl.lxcay.MyAidlInterface) iin); } return new com.aidl.lxcay.MyAidlInterface.Stub.Proxy(obj); } //这个被重写是因为,咱们的com.aidl.lxcay.MyAidlInterface类extends android.os.IInterface 所以需要提供一个 asBinder 对象 @Override public android.os.IBinder asBinder() { return this; } //这个是提供给Binder驱动在接受到消息的时候,回调的方法。里面对应的就是aidl接口描述文件里面的固定格式 @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_login: { data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); int _arg1; _arg1 = data.readInt(); //---------------->> boolean _result = this.login(_arg0, _arg1); reply.writeNoException(); reply.writeInt(((_result) ? (1) : (0))); return true; } case TRANSACTION_sayHello: { data.enforceInterface(DESCRIPTOR); com.aidl.lxcay.Person _arg0; if ((0 != data.readInt())) { _arg0 = com.aidl.lxcay.Person.CREATOR.createFromParcel(data); } else { _arg0 = null; } ////------------------------>> java.lang.String _result = this.sayHello(_arg0); reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); } //这个代理类,是客户端跟服务端之间的一个桥梁,通过阅读以下代码 ①方法 跟②方法,我们可以大致知道他们之间是怎么通讯的。 private static class Proxy implements com.aidl.lxcay.MyAidlInterface { //mRemote 为 Binder的引用 private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { //在Binder 的驱动中 mRemote 也重载了transact() 函数 mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } //①方法 @Override public boolean login(java.lang.String name, int age) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); boolean _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(name); _data.writeInt(age); //在向Binder通讯的时候,执行以下一句代码,驱动执行完毕之后成功,最后会回调 上面的 //public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)方法 mRemote.transact(Stub.TRANSACTION_login, _data, _reply, 0); _reply.readException(); _result = (0 != _reply.readInt()); } finally { _reply.recycle(); _data.recycle(); } return _result; } //②方法 @Override public java.lang.String sayHello(com.aidl.lxcay.Person p) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); if ((p != null)) { _data.writeInt(1); p.writeToParcel(_data, 0); } else { _data.writeInt(0); } mRemote.transact(Stub.TRANSACTION_sayHello, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_login = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_sayHello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public boolean login(java.lang.String name, int age) throws android.os.RemoteException; public java.lang.String sayHello(com.aidl.lxcay.Person p) throws android.os.RemoteException; }
ServiceManager 可以得到android系统的各个 ServiceManger对象,而每一个ServiceManger对象,又持有着各自对应的Binder 引用。
所以说,ServiceManager是Binder 驱动的一个引子,在IPC中 是客户端和服务端进行通信的媒介
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories