Android AIDL 教程 (一)—— 简单的示例
2017-10-26 20:22
405 查看
AndroidStudio 引用 aidl 文件的两种方法
Android AIDL 教程 (一)—— 简单的示例
Android AIDL 传递对象(Parceable)
AIDL(Android Interface Definition Language)是Android系统自定义的接口描述语言。可以用来实现进程间的通讯。
在 Android 中,要实现进程间的通讯,一般来说,有以下几种方式:
使用 Bundle
最常见的的是我们通过特定的 Action 或者 data 启动另外一个应用的 Activity 或者 service。我们可以将要传递的数据封装在 bundle 当中。
文件共享
两个应用读取某个文件,从而达到进程通讯的问题,不过这种方法需要处理好文件锁的问题,不然很容易引发数据错乱。
使用 Messenger
Messenger 进行进程间的通讯是串行的,而且是单向的,如果客户端和服务端想进行双向通讯,需要维护两个 Messenger,相对比较麻烦
使用 AIDL
通常服务端需要实现一个 Service,来处理客户端的请求
接下来让我们一起来实现一个简单功能,通过一哥 app(Clilent) 唤起另外一个 APP (Server),并进行两者之间的通讯。首先,我们先来看一下服务端的实现。
将请求抽象成接口,并编写 aidl 文件;
编写一个 Service,实现接口,处理客户端的请求,并将 binder 返回回去;
在 AndroidManifet 配置 Service,将我们的 Service 暴露出去。
Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
String
CharSequence
List
List 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 可选择将 List 用作“通用”类(例如,List)。另一端实际接收的具体类始终是 ArrayList,但生成的方法使用的是 List 接口。
Map
实现 Parceable 的自定义类型
注意事项
在 aidl 文件中,除了 Java 编程语言中的所有原语类型、String、CharSequence、List、Map,其他在 AIDL 文件中用到的类,你必须使用 import 语句导入,否则会报错。
当你使用实现Parceable 的自定义类型的时候,当其作为参数的时候,你必须为其制定是输入或者是输出参数。
如
有人可能会这样想,既然 inout 表示客户端和服务端都可以修改该类型,那我们平时在写 aidl 文件的时候,直接在方法参数前面加上 inout 修饰就 OK了,省得去区分。
这样做法当然不行,既然双方都可以修改,那系统的开销肯定会比较大。就好比管道一样。
说了这么多,接下来让我们一起来看一下例子 IEasyService.aidl
这个 aidl 文件很接口,只有两个方法,connect 和 disConnect 方法。
![](http://ww1.sinaimg.cn/large/9fe4afa0gy1fkvwxe07qej20ca0dz3z1.jpg)
这里我们把 aidl 文跟 Java 文件中放在一起,需要在 build.gradle 中配置
关于怎样在 AndroidStudio 中引用 aidl 文件的,可以参考我的这一篇文章 AndroidStudio 引用 aidl 文件的两种方法
这个 Service 所做的动作就是当客户端连接上的时候,会启动我们的 Service,此时会调用 Service 的 onBInd 方法,在 onBinder 方法里面,我们将 mIBinder (实现了 IEasyService.Stub 接口)返回回去。他充当客户端和服务端的桥梁,通过他我们可以进行通讯。
至于这个 IEasyService.Stub 是什么呢?其实当我们在 AndroidStudio 里面编写完 aidl 文件,重新 make project 一下,就会自动生成了。
其中 android:exported=”true” 表示别的进程可以访问,这个是必须配置的。android:process=”:remote” 表示运行在 :remote 进程,不配置的话默认运行所在的 App 进程,这个可以不配置。
通过服务端 Service 的 Action 启动, 当启动 Service 成功的时候,将服务端返回的 Binder 保存下来并转化成相应的实例。
之后如果想与服务端通讯,通过保存下来的 Binder,即可调用服务端的方法。
第一步:将服务端的 aidl 文件 copy 过来,注意要放在同一个包下
![](http://ww1.sinaimg.cn/large/9fe4afa0gy1fkvvj9qftij20c00bodg7.jpg)
第二步,通过服务端 Service 的 Action 启动, 当启动 Service 成功的时候,将服务端返回的 Binder 保存下来并转化成相应的实例
当我们点击按钮的时候,我们通过 Action 去启动远程 servic。
测试将会启动远程 Service,及服务端的 EasyService,并调用 onBind 方法,打印出相应信息。
第三步:如果想与服务端通讯,通过保存下来的 Binder,即可调用服务端的方法。
比如当我们点击按钮的时候,调用 connect 方法。
此时将会调用远程 service 的 mIbinder 的 connect 方法,log 中输出
关于怎样在 AndroidStudio 中,配置 aidl 的,可以参看 AndroidStudio 引用 aidl 文件的两种方法
DEMO 下载地址
最后的最后,卖一下广告,欢迎大家关注我的微信公众号,扫一扫下方二维码或搜索微信号 stormjun,即可关注。 目前专注于 Android 开发,主要分享 Android开发相关知识和一些相关的优秀文章,包括个人总结,职场经验等。
Android AIDL 教程 (一)—— 简单的示例
Android AIDL 传递对象(Parceable)
AIDL(Android Interface Definition Language)是Android系统自定义的接口描述语言。可以用来实现进程间的通讯。
在 Android 中,要实现进程间的通讯,一般来说,有以下几种方式:
使用 Bundle
最常见的的是我们通过特定的 Action 或者 data 启动另外一个应用的 Activity 或者 service。我们可以将要传递的数据封装在 bundle 当中。
文件共享
两个应用读取某个文件,从而达到进程通讯的问题,不过这种方法需要处理好文件锁的问题,不然很容易引发数据错乱。
使用 Messenger
Messenger 进行进程间的通讯是串行的,而且是单向的,如果客户端和服务端想进行双向通讯,需要维护两个 Messenger,相对比较麻烦
使用 AIDL
AIDL 简介
aidl 一般用来进程通讯。一般来说,主要有两种角色,客户端 (Client)和服务端(Server)。服务端
一般用来处理客户端的请求,他把与客户端通讯的方式抽象成接口,并编写成 AIDL 文件。通常服务端需要实现一个 Service,来处理客户端的请求
客户端
通常我们需要将服务端 的 AIDL 文件 copy 过来,并通过 Intent 的方式来启动我们服务端的 Service。接下来让我们一起来实现一个简单功能,通过一哥 app(Clilent) 唤起另外一个 APP (Server),并进行两者之间的通讯。首先,我们先来看一下服务端的实现。
服务端的实现
服务端的实现,一般来说,需要以下步骤:将请求抽象成接口,并编写 aidl 文件;
编写一个 Service,实现接口,处理客户端的请求,并将 binder 返回回去;
在 AndroidManifet 配置 Service,将我们的 Service 暴露出去。
将请求抽象成接口,编写 aidl 文件
一般来说, AIDL 文件支持以下类型Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
String
CharSequence
List
List 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 可选择将 List 用作“通用”类(例如,List)。另一端实际接收的具体类始终是 ArrayList,但生成的方法使用的是 List 接口。
Map
实现 Parceable 的自定义类型
注意事项
在 aidl 文件中,除了 Java 编程语言中的所有原语类型、String、CharSequence、List、Map,其他在 AIDL 文件中用到的类,你必须使用 import 语句导入,否则会报错。
当你使用实现Parceable 的自定义类型的时候,当其作为参数的时候,你必须为其制定是输入或者是输出参数。
in 表示输入参数,即服务端可以修改该类型 out 表示输出参数,即客户端可以修改该类型,客户端不行 inout 表示客户端和服务端都可以修改该类型
如
void onSuccess(int code,in MusicInfo musicInfo);
有人可能会这样想,既然 inout 表示客户端和服务端都可以修改该类型,那我们平时在写 aidl 文件的时候,直接在方法参数前面加上 inout 修饰就 OK了,省得去区分。
这样做法当然不行,既然双方都可以修改,那系统的开销肯定会比较大。就好比管道一样。
说了这么多,接下来让我们一起来看一下例子 IEasyService.aidl
package xj.musicserver.easy; // Declare any non-default types here with import statements interface IEasyService { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void connect(String mes); void disConnect(String mes); }
这个 aidl 文件很接口,只有两个方法,connect 和 disConnect 方法。
![](http://ww1.sinaimg.cn/large/9fe4afa0gy1fkvwxe07qej20ca0dz3z1.jpg)
这里我们把 aidl 文跟 Java 文件中放在一起,需要在 build.gradle 中配置
sourceSets { main { jniLibs.srcDirs = ['libs'] aidl.srcDirs = ['src/main/java'] } }
关于怎样在 AndroidStudio 中引用 aidl 文件的,可以参考我的这一篇文章 AndroidStudio 引用 aidl 文件的两种方法
编写一个 Service,实现接口,处理客户端的请求,并将接口返回回去
public class EasyService extends Service { private static final String TAG = "EasyService"; public EasyService() { } IEasyService.Stub mIBinder=new IEasyService.Stub() { @Override public void connect(String mes) throws RemoteException { LogUtil.i(TAG,"connect: mes =" + mes); } @Override public void disConnect(String mes) throws RemoteException { LogUtil.i(TAG, "disConnect: mes =" +mes); } }; @Override public IBinder onBind(Intent intent) { LogUtil.i(TAG,"onBind: intent = "+intent.toString()); return mIBinder; } @Override public boolean onUnbind(Intent intent) { LogUtil.i(TAG,"onUnbind: ="); return super.onUnbind(intent); } @Override public void onDestroy() { LogUtil.i(TAG,"onDestroy: ="); super.onDestroy(); } }
这个 Service 所做的动作就是当客户端连接上的时候,会启动我们的 Service,此时会调用 Service 的 onBInd 方法,在 onBinder 方法里面,我们将 mIBinder (实现了 IEasyService.Stub 接口)返回回去。他充当客户端和服务端的桥梁,通过他我们可以进行通讯。
至于这个 IEasyService.Stub 是什么呢?其实当我们在 AndroidStudio 里面编写完 aidl 文件,重新 make project 一下,就会自动生成了。
将服务端的 Service 暴露出去
在 AndroidManifest 文件下,配置 Service 的 action 及 exported 等信息。其中 android:exported=”true” 表示别的进程可以访问,这个是必须配置的。android:process=”:remote” 表示运行在 :remote 进程,不配置的话默认运行所在的 App 进程,这个可以不配置。
<service android:name=".easy.EasyService" android:enabled="true" android:exported="true" android:process=":remote"> <intent-filter> <action android:name="xj.musicserver.easy.IEasyService"/> </intent-filter> </service>
客户端的实现
将服务端的 aidl 文件 copy 过来,注意要放在同一个包下。通过服务端 Service 的 Action 启动, 当启动 Service 成功的时候,将服务端返回的 Binder 保存下来并转化成相应的实例。
之后如果想与服务端通讯,通过保存下来的 Binder,即可调用服务端的方法。
第一步:将服务端的 aidl 文件 copy 过来,注意要放在同一个包下
![](http://ww1.sinaimg.cn/large/9fe4afa0gy1fkvvj9qftij20c00bodg7.jpg)
第二步,通过服务端 Service 的 Action 启动, 当启动 Service 成功的时候,将服务端返回的 Binder 保存下来并转化成相应的实例
当我们点击按钮的时候,我们通过 Action 去启动远程 servic。
case R.id.btn_start_service: LogUtil.i(TAG,"onButtonClick: btn_start_service="); Intent intent = new Intent(ACTION); // 注意在 Android 5.0以后,不能通过隐式 Intent 启动 service,必须制定包名 intent.setPackage(XJ_MUSICSERVER); bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE); private static final String ACTION = "xj.musicserver.easy.IEasyService"; private IEasyService mIEasyService; ServiceConnection mServiceConnection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIEasyService = IEasyService.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mIEasyService=null; } };
测试将会启动远程 Service,及服务端的 EasyService,并调用 onBind 方法,打印出相应信息。
xj.musicserver:remote I/MusicInterface: EasyService :onBind: intent = Intent { act=xj.musicserver.easy.IEasyService pkg=xj.musicserver }
第三步:如果想与服务端通讯,通过保存下来的 Binder,即可调用服务端的方法。
比如当我们点击按钮的时候,调用 connect 方法。
case R.id.btn_contact: LogUtil.i(TAG,"onButtonClick: btn_contact="); if(mIEasyService!=null){ mIEasyService.connect(" Cilent connect"); }
此时将会调用远程 service 的 mIbinder 的 connect 方法,log 中输出
xj.musicserver:remote I/MusicInterface: EasyService :connect: mes = Cilent connect
注意事项
客户端和服务端的 aidl 文件必须放在同一个目录下关于怎样在 AndroidStudio 中,配置 aidl 的,可以参看 AndroidStudio 引用 aidl 文件的两种方法
DEMO 下载地址
最后的最后,卖一下广告,欢迎大家关注我的微信公众号,扫一扫下方二维码或搜索微信号 stormjun,即可关注。 目前专注于 Android 开发,主要分享 Android开发相关知识和一些相关的优秀文章,包括个人总结,职场经验等。
![](http://ww1.sinaimg.cn/large/9fe4afa0gy1fky6yqvcbbj209k09k748.jpg)
相关文章推荐
- android 开源图表库MPChart最简单使用方法示例教程Demo--折线图 柱状图
- Android中的AIDL及简单示例
- 简单的android进程间(远程)服务通信示例【AIDL方式】
- android简单的AIDL使用示例
- 一个简单的demo学习Android远程Service(AIDL的使用)
- Android 基础教程之---动态更改屏幕方向的简单例子(LANDSCAPE与PORTRAIT)!
- Android高手进阶教程(二十五)之---Android 中的AIDL!!!
- Android实现简单的下拉阻尼效应示例代码
- Android基础教程(三)之-----简单的Button事件响应综合提示控件Toast的应用
- Android简易实战教程--第十八话《ListView显示,简单的适配器SimpleAdapter》
- Android Binder 机制初步学习 笔记(四,完结)—— Binder 简单应用示例
- android音乐播放简单实现的简单示例(MediaPlayer)
- Android中ProgressDialog的简单示例
- Android动画Animation简单示例
- Android开发——Fragment简单示例(二)制作一个应用菜单导航栏
- android菜鸟学习笔记13----Android控件(二) 自定义控件简单示例
- phonegap 开发入门 PhoneGap官方网站上有详细的入门示例教程,这里,我针对使用PhoneGap进行Android移动应用的开发对其官网的Get Started进行一些介绍、补充。 Ste
- Android真正简单的教程-第十二枪(ViewFlipper实现滑动效果)
- Android简明开发教程十三:Option Menu 画笔示例
- Android与JavaSocket的简单示例