接收 ces 消息 底层 反序列化 arraylist arc 实现
一. AIDL 的意义:
AIDL 全称是 Android Interface Definition Language, 是 android 接口定义语言。AIDL 就是为了避免我们一遍遍的写一些千篇一律的代码而出现的一个模板。
目的: 实现进程间通信,而且在能在多进程并发的情况下进行进程间的通信。
与 Messenger 的区别: Messenger 是以串行的方式处理客户端发来的消息,如果有大量的并发请求那么 Messenger 就不大适合这些情况了,同时 Messenger 的作用主要是为了传递消息,很多的时候我们可能需要跨进程调用服务端的方法,这种情形用 Messenger 就无法做到了,但是 AIDL 可以。AIDL 也是 Messenger 的底层实现,因此 Messenger 的本质也是 AIDL,只不过系统为我们做了封装方便上层的调用。
二. AIDL 的语法:
(1) 文件类型:用 AIDL 书写的文件的后缀是 .aidl,而不是 .java。
(2) 数据类型: AIDL 默认支持一些数据类型,在使用这些数据类型的时候是不需要导包的,但是除了这些类型之外的数据类型,在使用之前必须导包,就算目标文件与当前正在编写的 .aidl 文件在同一个包下——在 Java 中,这种情况是不需要导包的。比如,现在我们编写了两个文件,一个叫做 Book.java ,另一个叫做 BookManager.aidl,它们都在 com.lypeer.aidldemo 包下 ,现在我们需要在 .aidl 文件里使用 Book 对象,那么我们就必须在 .aidl 文件里面写上 import com.lypeer.aidldemo.Book; 哪怕 .java 文件和 .aidl 文件就在一个包下。
· 基本数据类型(int,long,char,boolean,double,boolean,short,byte)
· String 类型和 CharSequence 类型;
· List 类型: 只支持 ArrayList,里面的每个元素必须能够被 AIDL 支持,List 支持泛型;
· Map 类型: 只支持 HashMap,里面的每个元素必须能够被 AIDL 支持,包括 key 和 value,Map 不支持泛型 。
· Parcelable : 所有事项了 Parcelable 接口的对象;
· AIDL: 所有的 AIDL 接口本身也可以在 AIDL 文件中使用。
两种 AIDL 文件:所有的 AIDL 文件大致可以分为两类。一类是用来定义 parcelable 对象,以供其他 AIDL 文件使用 AIDL 中非默认支持的数据类型的。一类是用来定义方法接口,以供系统使用来完成跨进程通信的。可以看到,两类文件都是在 "定义" 些什么,而不涉及具体的实现,这就是为什么它叫做 "Android 接口定义语言"。
举个例子:
例子 1:
- // Book.aidl
- //第一类AIDL文件的例子
- //这个文件的作用是引入了一个序列化对象 Book 供其他的AIDL文件使用
- //注意:Book.aidl与Book.java的包名应当是一样的
- package com.ryg.chapter_2.aidl; //注意parcelable是小写
- parcelable Book;
例子 2:
- //IBookManager.aidl//第二类AIDL文件的例子package com.ryg.chapter_2.aidl;
- //导入所需要使用的非默认支持数据类型的包
- import com.ryg.chapter_2.aidl.book;
- interface IBookManager{
- //所有的返回值前都不需要加任何东西,不管是什么数据类型List getBookList();
- //传参时除了Java基本类型以及String,CharSequence之外的类型//都需要在前面加上定向tag,具体加什么量需而定
- void addBook(in Book book);
- }
对象类要实现 Parcelable 接口:
参考这个 bolg: http://blog.csdn.net/luoyanglizi/article/details/51980630
将要传输的数据转化为能够在内存之间流通的形式。这个转化的过程就叫做序列化与反序列化。
比如现在我们要将一个对象的数据从客户端传到服务端去,我们就可以在客户端对这个对象进行序列化的操作,将其中包含的数据转化为序列化流,然后将这个序列化流传输到服务端的内存中去,再在服务端对这个数据流进行反序列化的操作,从而还原其中包含的数据——通过这种方式,我们就达到了在一个进程中访问另一个进程的数据的目的。
AIDL 中的 in,out,inout:
http://blog.csdn.net/luoyanglizi/article/details/51958091
AIDL 中的定向 tag 表示了在跨进程通信中数据的流向,其中 in 表示数据只能由客户端流向服务端, out 表示数据只能由服务端流向客户端,而 inout 则表示数据可在服务端与客户端之间双向流通。其中,数据流向是针对在客户端中的那个传入方法的对象而言的。in 为定向 tag 的话表现为服务端将会接收到一个那个对象的完整数据,但是客户端的那个对象不会因为服务端对传参的修改而发生变动;out 的话表现为服务端将会接收到那个对象的参数为空的对象,但是在服务端对接收到的空对象有任何修改之后客户端将会同步变动;inout 为定向 tag 的情况下,服务端将会接收到客户端传来对象的完整信息,并且客户端将会同步服务端对该对象的任何变动。
因为默认生成的模板类的对象只支持为 in 的定向 tag 。为什么呢?因为默认生成的类里面只有 writeToParcel() 方法,而如果要支持为 out 或者 inout 的定向 tag 的话,还需要实现 readFromParcel() 方法——而这个方法其实并没有在 Parcelable 接口里面,所以需要我们从头写。
readFromParcel() 方法:
添加了 readFromParcel() 方法之后,我们的 Book 类的对象在 AIDL 文件里就可以用 out 或者 inout 来作为它的定向 tag 了。
三. 在 androidstudio 快速生成 aidl 文件
在 eclipse
四. 后记
过程遇到的报错:
(1)java.lang.SecurityException: Binder invocation to an incorrect interface 报错问题
解决方法: 客户端的 aidl 文件包名要与服务端的包名一样
(2)报错: 系统找不到 Book.java (对象)文件
解决方法一:
- sourceSets {
- main {
- java.srcDirs = ['src/main/java', 'src/main/aidl']
- }
- }
解决方法 2:
把 java 文件放到 java 包下去:把 Book.java 放到 java 包里任意一个包下,保持其包名不变,与 Book.aidl 一致。只要它的包名不变,Book.aidl 就能找到 Book.java ,而只要 Book.java 在 java 包下,那么系统也是能找到它的。
例子:
把客户端和服务端都运行到同一个虚拟机上
最后成功的 logcat
客户端
服务端
AIDL 的例子 demo 下载传送门: https://github.com/Qinxiaoshou/AIDLDemo
android 的 AIDL
来源: http://www.bubuko.com/infodetail-2091278.html