AIDL 简介以及使用
1 AIDL简介
AIDL(Android 接口定义语言),可以使用它定义客户端与服务端进程间通信(IPC)的编程接口。在
Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进程都分 隔开来。可是有时候我们又有应用间进行互动的需求,比较传递数据或者任务委托等, AIDL就是为了满 足这种需求而诞生的。通过AIDL,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法, 从而满足进程间通信的需求。
AIDL是用于定义服务端和客户端通信接口的一种描述语言,可以拿来生产IPC代码,从某种意义上说
AIDL其实就是一个模板,因为在使用过程中,实际起作用的并不是AIDL文件,而是据此生产的一个
Interface的实例代码, AIDL其实是为了避免我们重复写代码而出现的一个模板。
2,为什么要设计这门语言?
设计这门语言的目的是为了实现进程间通信,尤其是在涉及多进程并发情况下的进程间通信。
3,它有哪些语法?
其实AIDL这门语言非常的简单,基本上它的语法和 Java 是一样的,只是在一些细微处有些许差别——毕竟它只是被创造出来简化Android程序员工作的,太复杂不好——所以在这里我就着重的说一下它和 Java 不一样的地方。主要有下面这些点:
文件类型:用AIDL书写的文件的后缀是 .aidl,而不是 .java。
数据类型:AIDL默认支持一些数据类型,在使用这些数据类型的时候是不需要导包的,但是除了这些类型之外的数据类型,在使用之前必须导包,就算目标文件与当前正在编写的 .aidl 文件在同一个包下——在 Java 中,这种情况是不需要导包的。比如,现在我们编写了两个文件,一个叫做 Book.java ,另一个叫做 BookManager.aidl,它们都在 com.lypeer.aidldemo 包下 ,现在我们需要在 .aidl 文件里使用 Book 对象,那么我们就必须在 .aidl 文件里面写上 import com.lypeer.aidldemo.Book; 哪怕 .java 文件和 .aidl 文件就在一个包下。
默认支持的数据类型包括:
Java中的八种基本数据类型,包括 byte,short,int,long,float,double,boolean,char。
String 类型。
CharSequence类型。
List类型:List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable(下文关于这个会有详解)。List可以使用泛型。
Map类型:Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是定义的parcelable。Map是不支持泛型的。
4. 使用流程
1 . 在 .aidl 文件中定义 AIDL 接口,并将其添加到应用工程的 src 目录下,创建完成之后 rebuild 2. Android SDK 工具会自动生成基于该 .aidl 文件的 IBinder 接口,具体的业务对象实现这个接口, 这个具体的业务对象也是 IBinder 对象,当绑定服务的时候会根据实际情况返回具体的通信对象 (本地还是代理)
3. 将客户端绑定到该服务上,之后就可以调用 IBinder 中的方法来进行进程间通信(IPC)
4.1下面从几个方面介绍AIDL的使用
1 . 创建.aildl 文件
2. 具体的业务对象实现基于 .aidl 文件生成的接口
3. 向客户端公开接口
4. 客户端远程调用
5. 验证 AIDL
4.1.1 创建.aildl 文件
在 AIDL 中可以通过可带参数以及返回值的一个或多个方法来声明接口,参数和返回值可以是任意类 型, AIDL 中支持的数据类型如下:
java 的 8 种数据类型: byte、 short、 int、 long、 float、 double、 boolean、 char
除此之外支持 String、 charSequence、 List、 Map
自定义数据类型 如果参数或返回值类型为 List 或 Map 时:
List 中的所有元素都必须是 AIDL 支持的数据类型、其他 AIDL 生成的接口或自己声明的可打包类 型。可选择将 List 用作“通用”类(例如, List)。另一端实际接收的具体类始终是 ArrayList,但生 成的方法使用的是 List 接口。
Map 中的所有元素都必须是 AIDL 支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类 型。 不支持通用 Map(如 Map 形式的 Map)。 另一端实际接收的具体类始终 是 HashMap,但生成的方法使用的是 Map 接口。
4.1.2 具体的业务对象实现基于 .aidl 文件生成的接口
1.首先,在工程的 src 目录下创建 .aidl 文件,具体如下图所示:
2.打开IPersonAidlInterface.aidl,在 .aidl 文件中添加具体的业务方法,文件内容如下:
package com . manu . aidl demo ;// Declare any non-default types here with import statementsinterface IPersonAi dlInterface {//具体的业务void setName (String name) ;void setAge (int age) ;String getInfo () ;/*** Demonst rates some basic types that you can use as paramete rs* and return values in AIDL .*/void basicTypes (int anInt , long aLong , boolean aBoolean , float aFloat , double aDouble , String aString) ;
}
3.然后,重新 rebuild project , Android SDK 工具会在相应的目录生成对应的与 .aidl 文件同名的 .java
接口文件,具体目录如下:
4. 那么这个业务要体现在什么地方呢,从上面可知 Stub 是一个抽象类,那么它所提供的具体业务必 然需要一个具体的实现类来完成,下面实现这个具体的业务类,具体如下:
public class IPersonImpl extends IPersonAi dlInterface . Stub {private String name ;private int age ;@Overridepublic void setName (String name) throws RemoteExcepti on {this . name = name ;}@Overridepublic void setAge (int age) throws RemoteExcepti on {this . age = age ;}@Overridepublic String getInfo () throws RemoteExcepti on {return "My name is "+name+" , age is "+age+" ! " ;}@Overridepublic void basi cTypes (int anInt , long aLong , boolean aBoolean , float aFloat , double aDouble , String aString) throws RemoteExcepti on {}
}
3.3.3 向客户端公开接口
创建一个 Service 以便对外提供具体的业务,具体如下:
// Servicepublic class PersonSe rvice extends Service {publicPe rsonService () {}@Overridepublic IBinder onBind (Intent intent) {return new IPersonImpl () ;}
}
当外部调用 bindService() 方法绑定服务时,就会调用 onBind() 方法返回 IBinder 对象,这个 IBinder
对象也是具体的业务对象,如这里的 onBind() 方法返回的也是具体的业务对象,两者是统一的。此外, 创建的 Service 要在 AndroidManifest.xml 文件中声明,具体如下:
serviceandroid : name=" . PersonService"android : enabled="true"android : exported="true"android : process=" : remote">
</service>
其中使用 process 关键字表示为该服务开启一个独立的进程, remote 可任意,表示进程名称, ":"将会 在主进程(进程名为包名)添加新名称作为新进程的名称,如 com.hopu.study 将会变成
com.hopu.study:remote。
4.1.3 客户端远程调用
通过上面几步完成了服务的搭建,并将服务运行在独立进程中,下面主要就是客户端的具体调用了,具 体实现参考如下:
public class MainActivity extends AppCompatActi vity {private Button btn_start_service , btn_stop_service , btn_call _remote ;private static final String TAG = "MainActivity" ;private IPrsonAidl Interface iPersonAi dlInterface ;@Overrideprotected void onCreate (Bundl e savedInstanceState) {super . onCreate (savedInstanceState) ;setContentView(R . layout . activity_main) ;btn_start_service = findViewById (R . i d . btn_start_service) ;btn_stop_se rvi ce = fi ndVi ewById (R.id.btn_stop_service) ;btn_cal l _remote = findViewById (R . id . btn_call _remote) ;btn_start_servi ce . setOnClickListener (new View . OnClickListene r () {@Overridepublic void onClick(Vi ew v) {bindService Click(v) ;} }) ;btn_stop_servi e . setOnClickListener (new Vi ew . OnCl i ckLi stene r () {@Overridepublic void onClick(View v) {unbindSe rviceClick(v) ;}}) ;btn_call _remote . setOnClick Listener (new View . OnClick Listener () {@Overr depublic void onClick(View v) {call RemoteClick(v) ;}}) ;}public void bindService Cick(View view) {Log . i (TAG , "绑定服务 . . . ") ;Intent intent = new Intent (this , PersonSe rvice . class) ;// 绑定服务时自动创建服务bindService (intent , conn , Context . BIND_AUTO_CREATE) ;}public void unbindSe rviceCl i ck(View view) {Log . i (TAG , "解绑服务 . . . ") ;unbindService (conn) ;}public void call RemoteClick(View view) {Log . i (TAG , "远程调用具体服务 . . . ") ;try {iPersonAidl Interface . setName ("Tom") ;iPersonAidl Interface . setAge (10) ;String info = iPersonAidl Interface . getInfo () ;System . out . println ("这是远程调用的服务信息: "+info) ;} catch (RemoteExcepti on e) {e . printStackTrace () ;}}private Servi ceConnection conn = new Service Connection () {@Overridepublic void onService Connected (ComponentName name , IBinde rservice) {// 根据实际情况返回 IBinder 的本地对象或其代理对象iPersonAidl Interface = IPersonAidl Interface . Stub . asInterface (service) ;System . out . println ("具体的业务对象: "+iPersonAi dlInterface) ;}@Overridepublic void onService Disconnected (ComponentName name) {// Service 意外中断时调用
}};
4.1.4 验证 AIDL
通过前面几步,服务端与客户端已经完成,下面来验证能否调用具体的业务,这里分两种情况:
1、相同进程 创建 Service 的时候不要在 AndroidManifest.xml 文件中不要使用 process 开启独立进程即可,此时服 务进程默认与客户端属于统一进程,结果如下:
2、不同进程 显然,如果服务与客户端处于不同进程,也就是常常说的进程间通信,具体是由 IBinder 对象的代理对 象完成,反之,使用本地对象,也就是本地的 IBinder 对象,具体就是实现 AIDL 的业务类所生成的对象
AIDL 简介以及使用相关推荐
- Android的IPC机制(一)——AIDL的使用
综述 IPC(interprocess communication)是指进程间通信,也就是在两个进程间进行数据交互.不同的操作系统都有他们自己的一套IPC机制.例如在Linux操作系统中可以通过管道. ...
- xamarin学习笔记A19(安卓AIDL)
(每次学习一点xamarin就做个学习笔记和视频来加深记忆巩固知识) 如有不正确的地方,请帮我指正. AIDL简介 AIDL(Android Interface Definition Langua ...
- android aidl空指针,AIDL使用笔记
最近这段时间在项目开发中使用到了AIDL,之前对这块的内容比较陌生.所以特地分享一下关于AIDL的一些使用知识,如果有什么写的不对的地方还请指出.这里先谢谢了!!! 本文知识点: AIDL简介 AID ...
- android应用开发全程实录出版
这本书经历了大半年的时间,终于可以和读者见面了.书籍由我和微度网http://www.microdu.com/其他两位资深开发者共同完成. 最近经历了很多,应该是人生的一个转折点吧.总会有一些选择,将 ...
- Android 跨进程通信大总结
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/111553746 本文出自[赵彦军的博客] 文章目录 1.Android进程 2.修 ...
- 操龙兵:非独立同分布学习
原文地址:非独立同分布 AIDL简介 "人工智能前沿讲习班"(AIDL)由中国人工智能学会主办,旨在短时间内集中学习某一领域的基础理论.最新进展和落地方向,并促进产.学.研相关从业 ...
- Android 4.0按键事件以及系统流程分析
Android 4.0中按键的处理流程 按键在Android系统中,有着不同的代表意义.以前的全键盘的手机代码没有阅读过,所以也不是很了解.本人介绍的是在触摸屏的手机上的按键消息的处理流程. 在现在触 ...
- Ninja简介-Android10.0编译系统(九)
摘要:Ninja具体干了什么? 阅读本文大约需要花费16分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢! 欢迎关注我的公众 ...
- Blueprint简介-Android10.0编译系统(六)
摘要:Android.bp由Blueprint进行解析翻译,最终通过soong build编译成ninja文件,那么Blueprint是什么呢? 阅读本文大约需要花费10分钟. 文章首发微信公众号:I ...
最新文章
- 如何读取比机器内存大的文件(内存4G,文件 8G,读取大文件) ?
- [lua]判断nginx收到的是否json
- php安装redis扩展详细步骤 不会可以加QQ
- Python--day46--MySQL视图
- 第五课 路由之初识路由
- 《剑指Offer》62:圆圈中最后剩下的数字(约瑟夫环)
- [线段树][树上差分] Jzoj P3397 雨天的尾巴
- qt利用QSplitter任意拆分窗口
- Mysql drop table 原理_mysql事务的实现原理
- Android基础(四) Fragment Part 1
- “630”落幕 光伏何去何从?
- 小程序 房租水电费记录管理_智慧物业管理小程序怎么开发?
- 最少承诺原则和单一职责原则_单一责任原则
- oracle数据库表空间容量查询及扩容
- 极限与连续知识点总结_大一上学期《高等数学》知识整理-第一章 极限与连续...
- java clh_【Java】CLH 自旋锁
- 目录服务器的互联网标准协议,2014年4月自学考试《互联网及其应用》试题
- 【无标题】asdas
- 网络游戏外挂制作(3)-1
- 基于校园生活一体化管理系统的需求分析
热门文章
- [导入][幻想情侣][2008热播韩剧][全16集+OST][韩语中字]
- mysql 字符串转日期及其他日期转换
- show slave status
- 【vs】开始运行、开始运行不调试区别
- sed基本用法介绍1
- Cas乐观锁的初步理解
- EasyX中使用背景音乐
- 网易云音乐HTML5随机音乐播放器源码
- WIN10搭建深度学习环境 GTX1080+CUDA9.0+cuDNN7.0+Python3.6+Tensorflow1.6.0
- 置换贴图(Displacement map),凹凸贴图(Bump map)与法线贴图(Normal map)的区别