AIDL进程间调用与Binder的简单介绍
Binder是安卓中特有的一种进程间通信(IPC)方式,从Unix发展而来的手段,通信双方必须处理线程同步、内存管理等复杂问题,传统的Socket、匿名通道(Pipe)、匿名管道(FIFO)、信号量(Semaphore)、消息队列等,这些都从Android中去掉了。Socket是一种比较成熟的通信手段,同步控制也很容易实现,但是用于进程间通信,效率不高。
Android是整个系统运行的中枢,因此,Android在提高Binder的效率方面也下足了功夫。Android在进程间传递数据使用的是共享内存的方式,这样数据只需要复制一次就能从一个进程到达另一个进程(一般的IPC都需要两部,从用户进程复制到内核,再从内核复制到服务进程),这样数据传输的效率就大大提高了。
Binder调用时会传递调用进程的euid到服务端,因此服务端可以通过检查调用进程的权限来决定是否允许其使用所调用的服务。
定义一个AIDL接口
你必须使用java语法来写一个.aidl文件来定义你的AIDL接口,保存它在应用程序持有服务和应用程序绑定到服务两种情况的源代码中(src/目录下)。
当你编译每个包含.aidl文件的应用程序时,AndroidSDK工具会在.aidl文件的基础上生成一个IBinder接口并且保存它在工程的gen/目录下。service服务必须适当地实现IBinder接口。客户应用程序应该绑定服务并且调用IBinder下的方法去执行IPC。
为了创造一个使用AIDL的bounded service绑定服务,有下列步骤。
1.创造一个.aidl文件
这个文件定义了带方法签名的程序接口。
2.实现接口
AndroidSDK工具生成了一个java语言的接口,基于你的.aidl文件。
这个接口有一个内部的抽象类叫Stub继承Binder并且实现你的AIDL接口中的方法。
你必须继承Stub类并且实现方法
3.暴露接口给客户
实现service和重写onBind()方法去返回你的Stub类的实现。
1.创建AIDL文件
AIDL使用一个简单的语法让你声明可以传参并有返回值的一个或多个方法。参数和返回值可以是任何类型,甚至是其它AIDL生成的接口。
你必须使用java程序语言构造.aidl文件。每个.aidl文件必须定义一个简单的接口,要求有接口声明和方法签名。
一般地,AIDL支持下列数据类型:
》所有的java程序语言的基本类型(像int,long,char,boolean等等)
》String
》CharSequence
》List
所有的List里面的元素必须是这个列表里面支持的数据类型或者其它AIDL生成的接口或者你已经声明的序列化。一个List可能选择被用来作为泛型类(例如,List)。实际的具体另一方面负责接口的总是ArrayList,虽然这个方法通常使用List接口。
》Map
同上。
你必须包含进import语句给每个不在上面列出来的额外类型,即使它们是定义在和你的接口一样的包里面。
当定义你的服务接口时,要意识到:
》方法可以传(take)0个或者多个参数,可以返回一个值或者void
》所有的非基本类型要求一个方向性的标签暗示数据走的哪条路。是in,out或者inout.基本的默认的是in,不会是其它的。
》所有的代码注释包含在.aidl文件中,在生成的IBinder接口中(除了在导入和包声明语句)
》仅仅支持方法;你不能在AIDL中expose暴露static fields静态域
简单地保存你的.aidl文件到你的工程src/目录下,并且当你编译你的程序时,SDK工具会在你的工程的gen/目录下生成IBinder接口文件。生成文件名字匹配.aidl文件名字,但是带有一个.java后缀名(例如,IRemoteService.aidl会生成IRemoteService.java)
如果你使用AndroidStudio,递增地编译会让binder类立即生成。如果你没有使用AS,那么Gradle工具在下次你编译你的应用程序的时候会是生成binder类,你应该用gradle
assembleDebug(或者gradle
assembleRelease),一旦你完成.aidl文件的编写,所以你的代码可以链接到生成的类。
2.实现接口
当你编译应用程序时,Android SDK工具会在你的.aidl文件后生成一个.java接口文件。生成的接口包含了一个子类Stub(例如,YourInterface.Stub),这是一个抽象的父亲接口的实现并且声明了所有.aidl文件里面的方法。
Stub也定义了一些少量的帮助方法,必须注意到asInterface(),这会传递一个IBinder(通常将会这个传递到客户端的onServiceConnected()回调方法)并且返回一个stub接口的实例。
可以去看Calling anIPC Method寻求更多的关于怎么做这个转换的介绍。
为了实现这个从.aidl生成的接口,集成生成的Binder接口(例如,YourInterface.Stub)并且实现从.aidl文件继承的方法。
这里是一个叫IRemoteService接口实现的例子(由IRemoteService.aidl文件定义),使用一个匿名的实例。
现在mBinder是一个Stub类的实例(aBinder),这定义了服务的RPC接口。
在下一步,这个实例是要暴露给客户,这样它们能和service交互。
这里是一些当你实现你的AIDL接口应该意识的规则:
》来电不保证会在主线程执行,所以你需要从一开始就考虑多线程并且合适地构建你的service服务做到线程安全。
》默认地,RPC调用是异步地。
如果你知道service会花去一些毫秒数去完成请求,你不应该从activity活动的主线程调用它,因为它可能hang暂停应用程序(Android可能会展示ANR对话框)-你应该开一个线程去调用它。
》异常要抛出去给调用着。
3.暴露接口给客户端
一旦你已经实现了给你的service的接口,你就需要暴露它给客户端这样他们能绑定它。
为了暴露接口给你的service。继承Service并且实现onBind()方法然后返回一个你实现的生成的Stub类的实例(就像之前讨论的)。
现在,当客户(比如一个Activity)调用bindService()去连接服务的时候,客户端的onServiceConnected()回调方法会收到mBinder实例,这由service's服务的onBind方法返回。
客户必须可以访问接口类,所以如果客户和service在不同的应用程序间,那么客户的应用程序必须在src/目录下有一个.aidl文件的复制(这会生成android.os.Binder接口-提供给客户访问AIDL方法)。
当客户在onServiceConnected回调方法中收到IBinder,这必须调用YourServiceInterface.Stub.asInterface(service)去转换成返回类型到YourServiceInterface类型。
当在eclipse中写了.aidl文件时会自动编译出Java文件,
android studio中用aidl文件生成对应的java文件,先在main目录下新建aidl文件夹,
然后再新建一个包名,这个包名要和manifest文件里面的包名匹配,再写一个aidl
文件,注意写package,然后build一下就可以在app/build/generated/source/aidl目录下找到一个debug(可能是release)目录,就可以看到我们生成的java文件了。
注意不用拷贝到src目录下,如果拷贝,AS会提示重复。
main目录下新建aidl文件夹,再随便new出一个包名,写对应的aidl文件,然后可以在build.gradle下面的android范围内,写sourceSets {
main {
aidl.srcDirs = ['src/main/aidl']
}
}
再对工程build一下也可以解决。
AIDL进程间调用与Binder的简单介绍的更多相关文章
- 【起航计划 037】2015 起航计划 Android APIDemo的魔鬼步伐 36 App->Service->Remote Service Binding AIDL实现不同进程间调用服务接口 kill 进程
本例和下个例子Remote Service Controller 涉及到的文件有RemoteService.java ,IRemoteService.aidl, IRemoteServiceCallb ...
- 服务 远程服务 AIDL 进程间通讯 IPC
Activity aidl接口文件 package com.bqt.aidlservice; interface IBinderInterface { /* 更改文件后缀为[.aidl]去掉 ...
- c# 进程间的通信实现之一简单字符串收发
使用Windows API实现两个进程间(含窗体)的通信在Windows下的两个进程之间通信通常有多种实现方式,在.NET中,有如命名管道.消息队列.共享内存等实现方式,这篇文章要讲的是使用Wi ...
- 输入系统:进程间双向通信(socketpair+binder)
一.双向通信(socketpair) socketpair()函数用于创建一对无名的.相互连接的套接子,如果函数成功,则返回0,创建好的套接字分别是sv[0]和sv[1]:否则返回-1,错误码保存于e ...
- 服务 远程服务 AIDL 进程间通讯 IPC 深化
示例 aidl接口文件 package com.bqt.aidlservice.aidl; parcelable Person; package com.bqt.aidlservice.aidl; ...
- [Android Pro] AIDL进程间传递自定义类型参数
1.创建.aidl 文件 AIDL 语法简单,用来声明接口,其中的方法接收参数和返回值,但是参数和返回值的类型是有约束的,且有些类型是需要 import,另外一些则无需这样做. AIDL 支持的数据类 ...
- Android Binder 进程间通讯机制梳理
什么是 Binder ? Binder是Android系统中进程间通讯(IPC)的一种方式,也是Android系统中最重要的特性之一.Binder的设计采用了面向对象的思想,在Binder通信模型的四 ...
- Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...
- Python多进程编程-进程间协作(Queue、Lock、Semaphore、Event、Pipe)
进程与进程之间是相互独立的,互不干扰.如果多进程之间需要对同一资源操作,就需要进程间共享变量,上一篇文章介绍了进程间共享数据的三大类Value.Array.Manager,这三种类的主要区别在于管理的 ...
随机推荐
- JqueryMobile- 搭建主模板
最近公司要开发手机端的,可是我没学过安卓,然后用HTML5+JQUERYMOBILE也可以做这些手机端的程序,做成个网页,发到网上,免强也行,于是开始了我JQUERYMOBILE的学习. 先放一下主模 ...
- [转载代码]VB.NET 中查询 Linq to SQL 执行时的SQL语句
在搜索使用LINQ TO SQL 添加数据后获得自增长ID的方法时,发现C#可以使用DebuggerWritter把使用Linq to SQL执行的SQL语句显示到即时窗口,于是在网上搜索到在VB.N ...
- CSS3教程:Transform的perspective属性设置
1 2 <div id="animateTest" style="-webkit-transform: perspective(400px) rotateY(4 ...
- DATE_FORMAT() 函数
DATE_FORMAT() 函数用于以不同的格式显示日期/时间数据DATE_FORMAT(now(),'%Y-%m-%d %T')
- Web.config之连接字介绍
一.连接字配置方式 web.config中有两种方式来配置连接字:<appsetting>中配置,<connectionStrings>中配置. 1.<appsettin ...
- Codeforces Round #329 (Div. 2) B. Anton and Lines 逆序对
B. Anton and Lines Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/593/pr ...
- Codeforces Round #326 (Div. 2) D. Duff in Beach dp
D. Duff in Beach Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/588/probl ...
- Lambda表达式实现有限状态机
实现状态机有多种模式,其中最灵活而强大的方式是通过迁移表来实现,该方式的缺点之一是需要编写大量小块代码去支持迁移表.而在C#3.0中,可以以一种非常优雅的方式实现. 除了有限状态机外,还有有限自动机, ...
- delphi 取得汉字的第一个字母
功能说明://取得汉字的第一个字母 function GetPYIndexChar( hzchar:string):char;begin caseWORD(hzchar[1])shl8+WORD(h ...
- delphi label1 文字在窗体上水平来回移动
//文字在窗体上水平来回移动 procedure TForm1.Timer1Timer(Sender: TObject);{ Timer1.Interval:=10;}begin if label1 ...