AIDL 一
2016-02-28 01:13
435 查看
AIDL一般的项目当中很少接触到,但是老被问到,因此基于实在不想知道它是什么东西的态度下来看看它,结果和预想差不多。这个东西其实和protobuf的使用方法比较类似,都是通过代码生成类,然后调用这个不能编辑的类里面的对象或方法。但我记得protobuf生成文件是通过一个exe执行后直接导出的,而aidl相对代码可读性要高一点并且IDE会帮你生成,里面方法或者参数的定义都是和protobuf一样预先在客户端和服务端约定好,这也是IDL的体现。
我们都知道AIDL是用于进程间通信的,线程间的通信是handler的职责范围而进程间的通信同样可以,那么就引入了Messenger。官方文档解释:它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。Messenger不复杂,查阅源码还是比较好理解的。
那么重点在于,Messenger是一个Parcelable类,Messenger又持有Handler对象,Handler持有IMessenger对象,IMessenger持有一个继承自Binder实现了IBinder的Stub,而这个Stub就是两个进程间通信所共用的对象,有了一个共同对象当然就可以以此为依据进行通信了。
代码上来看,服务端继承Service需要实现OnBind:
而客户端在连上服务端后要获取IBinder:
何为服务端,何为客户端,需要先了解本地service默认情况下运行在当前进程的主线程中,远程service运行再另一个进程中。而这两者区别在于service的定义:“android:process”。
那么了解上面的Messenger,就可以很好的理解AIDL的实现方式了,因为Messenger就是以AIDL的方式实现并封装好的,那么我们可以这样理解,通常说的aidl实现其实就是在一定规则或框架下自定义进程间通信,Messenger仅仅是一个android实现好了的可使用的API。那么aidl的实现规则里,为何会有service的参与,为何会有aidl文件,那么只要细心回想查看LocationManager之类的系统manager类,里面都会看到ILocationManager等等上面讲过的影子,是的,gps肯定是运行在不同的进程中与你的app交互的,而其实现方式肯定也是以aidl方式实现的,在Android系统中有很多的Manager,wifi的管理类叫WifiManager,蓝牙的管理类叫BluetoothManager,只要有xxxManager.java,就会有Ixxx.aidl,并且有xxxService.java。这个Ixxx.aidl就是实现Manager和Service通信的桥梁。总归一句话,aidl的实现规则实际上也是android系统服务实现的产物,如果还要究其原因,可以看老罗的源码分析,里面讲得很透彻。
aidl实现方式的规则:
1 自己写一个aidl文件,放在专门存放aidl文件的地方。android studio可以右击app module新建出来,但需注意gradle构建时的productFlavors不同会发生包名不一致而报错。该文件里面基本代码为:
看上去像java,但需谨慎的是,包名要一致,另一个是该文件里面定义的数据类型有的要引入有的不用:
所有基础类型(int, char, 等)
String,List,Map,CharSequence等类
其他AIDL接口类型
所有Parcelable的类
这个一试就知道了。
2 build项目,不报错就会生成一个java文件,目录在项目输出目录下。
3 一个继承自service的类,该类项目主目录下就可以(即和activity之类的文件同一个包名下就可以不用放在aidl文件的存放目录下),该类里基本代码为:
4 一个实现了ServiceConnection的类,与通信基本代码为:
连上服务后就可以通过iAidlInterface执行定义好的放在服务端的代码了。
5 初始化等等基本代码:
以上就是aidl的实现基本规则,按照这些套路做就行了。
我们都知道AIDL是用于进程间通信的,线程间的通信是handler的职责范围而进程间的通信同样可以,那么就引入了Messenger。官方文档解释:它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。Messenger不复杂,查阅源码还是比较好理解的。
那么重点在于,Messenger是一个Parcelable类,Messenger又持有Handler对象,Handler持有IMessenger对象,IMessenger持有一个继承自Binder实现了IBinder的Stub,而这个Stub就是两个进程间通信所共用的对象,有了一个共同对象当然就可以以此为依据进行通信了。
代码上来看,服务端继承Service需要实现OnBind:
@Override public IBinder onBind(Intent intent) { return new Messenger(mHandler).getBinder(); }
而客户端在连上服务端后要获取IBinder:
@Override public void onServiceConnected(ComponentName name, IBinder service) { messenger = new Messenger(service); }
何为服务端,何为客户端,需要先了解本地service默认情况下运行在当前进程的主线程中,远程service运行再另一个进程中。而这两者区别在于service的定义:“android:process”。
那么了解上面的Messenger,就可以很好的理解AIDL的实现方式了,因为Messenger就是以AIDL的方式实现并封装好的,那么我们可以这样理解,通常说的aidl实现其实就是在一定规则或框架下自定义进程间通信,Messenger仅仅是一个android实现好了的可使用的API。那么aidl的实现规则里,为何会有service的参与,为何会有aidl文件,那么只要细心回想查看LocationManager之类的系统manager类,里面都会看到ILocationManager等等上面讲过的影子,是的,gps肯定是运行在不同的进程中与你的app交互的,而其实现方式肯定也是以aidl方式实现的,在Android系统中有很多的Manager,wifi的管理类叫WifiManager,蓝牙的管理类叫BluetoothManager,只要有xxxManager.java,就会有Ixxx.aidl,并且有xxxService.java。这个Ixxx.aidl就是实现Manager和Service通信的桥梁。总归一句话,aidl的实现规则实际上也是android系统服务实现的产物,如果还要究其原因,可以看老罗的源码分析,里面讲得很透彻。
aidl实现方式的规则:
1 自己写一个aidl文件,放在专门存放aidl文件的地方。android studio可以右击app module新建出来,但需注意gradle构建时的productFlavors不同会发生包名不一致而报错。该文件里面基本代码为:
interface IAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); }
看上去像java,但需谨慎的是,包名要一致,另一个是该文件里面定义的数据类型有的要引入有的不用:
所有基础类型(int, char, 等)
String,List,Map,CharSequence等类
其他AIDL接口类型
所有Parcelable的类
这个一试就知道了。
2 build项目,不报错就会生成一个java文件,目录在项目输出目录下。
3 一个继承自service的类,该类项目主目录下就可以(即和activity之类的文件同一个包名下就可以不用放在aidl文件的存放目录下),该类里基本代码为:
public class IAidlService extends Service { @Override public void onCreate() { super.onCreate(); } @Override public void onDestroy() { super.onDestroy(); } @Nullable @Override public IBinder onBind(Intent intent) { return new IAidlInterface.Stub() { @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } }; } }
4 一个实现了ServiceConnection的类,与通信基本代码为:
public class IAidlServiceConnection implements ServiceConnection { public IAidlServiceConnection() { } @Override public void onServiceConnected(ComponentName name, IBinder service) { iAidlInterface = IAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { iAidlInterface = null; } }
连上服务后就可以通过iAidlInterface执行定义好的放在服务端的代码了。
5 初始化等等基本代码:
IAidlServiceConnection connection; IAidlInterface iAidlInterface; private void initService() { connection = new IAidlServiceConnection(); Intent i = new Intent(this, IAidlService.class); boolean ret = getApplicationContext().bindService(i, connection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); releaseService(); } private void releaseService() { getApplicationContext().unbindService(connection); connection = null; }
以上就是aidl的实现基本规则,按照这些套路做就行了。
相关文章推荐
- lintcdoe: Number of Airplanes in the Sky
- Leetcode ☞ 217. Contains Duplicate
- 【UVa】11413 – Fill the Containers
- GCJ--Millionaire (2008 APAC local onsites C)
- 关于main主函数的两个参数argc和argv
- ZOJ 3781 Paint the Grid Reloaded 图论 bfs
- 11.2 RAC: In "crsctl stat res -t" State Details May Be Missing or Incorrect (文档 ID 1086563.1)
- Hanoi Tower Troubles Again! (找规律)
- GetPostBackEventReference加RaisePostBackEvent实现自定义控件中回调传参
- Codeforces - AIM Tech Round (Div. 2)C - Graph and String
- ZOJ 3780 Paint the Grid Again
- 使用Keychain配置
- Leet Code OJ 70. Climbing Stairs [Difficulty: Easy]
- 1021 Fibonacci Again
- 集训队专题(7)1001 Drainage Ditches
- train validation test
- 1090 Higest Price in Supply Chain
- 102.Daikon Forge基础使用label、button、sprite、textureAtlas、font
- UVA 10976(p183)----Fractions Again?!
- VS2012 error C2664: “std::make_pair”:无法将左值绑定到右值引用