AIDL的理解与使用详解

来源:互联网 发布:windows文件名最大长度 编辑:程序博客网 时间:2024/05/21 20:51

    本篇文章将对Android中的AIDL服务的概念和创建AIDL服务的步骤进行介绍,结合简单的代码示例,力求更易理解。
本篇文章的demo链接如下:链接:http://pan.baidu.com/s/1dEVWXxR 密码:k9gk (结合代码,更易理解,推荐!)
AIDL:Android Interface Definition Language,即Android接口定义语言。
首先我们来看一下百度百科的回答(介绍的很详细):
什么是AIDL:

Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。

为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。

建立AIDL的服务步骤:

建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:
(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
实现AIDL接口的说明:
(1)AIDL接口只支持方法,不能声明静态成员;
(2)不会有返回给调用方的异常。
以上就是百度百科的回答,能大致对AIDL有个了解,可以知道AIDL就是专门是用来解决进程间通信的,但是缺少详细的实例解释。下面我就将结合自己所学的知识对AIDL做个介绍
首先明确几个概念
  (1)远程服务 运行在其他应用里面的服务(此处一定要区别servlet,没有关系)
  (2)本地服务 运行在自己应用里面的服务 
  (3)进行进程间通信  IPC
  (4)aidl Android interface Defination Language Android接口定义语言 专门是用来解决进程间通信的 
      此处就可以把AIDL理解为是跨进程访问的服务,即用本地应用访问远程服务。
--------------------------------------------------------------手动分割线---------------------------------------------------------------------
大致了解了AIDL的概念,下面来说一下建立AIDL服务的步骤:建立两个简单项目用来演示AIDL服务的创建过程,一个远程服务,一个本地服务,下面我们要实现的目的就是--->>>通过本地程序去访问远程服务中的service服务(这就是AIDL的作用
首先我们在远程服务中创建一个远端的服务,结构如下:
因为这是用来“被”调用的远程服务,所以MainActivity方法中暂不做任何修改,RemoteService就是用来远程调用的服务,IService是一个接口,里面暴露了RemoteService中想暴露出去的方法。
RemoteService代码如下:
//远程服务public class RemoteService extends Service {//[2]把我们定义的中间人对象返回@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}//在服务里面定义一个方法public void testMethod(){System.out.println("我是远程服务里面的方法");}//[1]定义中间人对象 private class MyBinder extends Binder implements Iservice{//调用testMethod方法@Overridepublic void callTestMethod() {testMethod();}}}
IService接口代码如下
public interface Iservice {//把想暴露的方法暴露出来public void callTestMethod();}

按照常理,在本地服务中,此时如果通过本地服务去调远程服务中的方法,此时在构造intent时会发现无法通过bindService(xxx.this, xxx.class);这个方法调用,所以此时应该考虑用隐式intent调用,所以此时还需要在配置文件中配置一下RemoteService,添加它的action为com.itheima.remoteservice
    //[1]调用bindservice 获取我们定义的中间人对象 Intent intent = new Intent();//设置一个actionintent.setAction("com.itft.remoteservice");//随便定义即可MyConn conn = new MyConn();//[2]目的是为了获取我们定义的中间人对象bindService(intent, conn, BIND_AUTO_CREATE);
然后我们应该在本地服务中去获取远程服务中的中间人对象(MyBinder),现在关键问题来了,在本地服务中无法获取远程服务中的中间人对象,———》》》》AIDL的用处来了!
//监视服务的状态private class MyConn implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {//获取中间人对象 iservice = Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {}}

下面是创建AIDL服务的正式过程;
1.来到远程服务的IService.java的文件目录中,将 IService.java 改名为 IService.aidl ,如下


2.进入eclipse,刷新一下工程,会发现工程报错了,此时先不要管,打开IService.aidl之后会发现AIDL不认识public关键字,所以把public关键字删掉即可,此时在gen目录下就自动生成了一个IService.java 文件
 
 打开IService.java文件会发现如下代码,代码的意思就是系统帮我们自动生成了一个Stub类,就是用于IPC(进程间通信)的,这个类继承Binder,而且实现了IService,其实这就是原来远程服务中MyBinder实现的方法

所以我们就可以进入远程服务的RemoteService中改一下,让中间人对象直接继承Stub,此时工程就不报错了
//[1]定义中间人对象 private class MyBinder extends Stub{//调用testMethod方法@Overridepublic void callTestMethod() {testMethod();}}

2.本地服务的目的就是拿到远程服务的中间人对象,此时中间人对象就是IService.java这个文件,现在的问题就是怎么才能拿到这个文件呢? 我们知道IService.java这个文件是通过IService.aidl自动生成的,那现在只要保证这两个应用程序的aidl文件是同一个,那这样本地服务就拿到了远程服务的IService.java文件。那怎么保证这两个项目的aidl文件是同一个呢?这里有一个规定,只要同一个aidl文件在同一个包内,那么系统就会认为这两个aidl文件是相同的。。。将远程服务的包名拷贝到本地服务中去,新建一个包,将远程服务的aidl文件拷贝到本地服务的新建的包下,可能我这里描述的不够准确,下面直接看如何操作的图片

这样的话在本地服务的gen目录下也会自动生成一个IService.java文件,也就是说,这样我们就能在本地服务中拿到远程服务的中间人对象了。

这里要注我们意一点,在获取中间人对象时,般采我们一用的是强制类型转换的方法,但是这里我们要采取另一种方法,直接进行下面的操即可中间人对象
// 监视服务的状态private class MyConn implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// 获取中间人对象iservice = Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {}}
此时AIDL服务构建完成,可以通过AIDL来调用远程服务中的方法了
public void click(View v) {try {iservice.callTestMethod();//调用代码} catch (RemoteException e) {e.printStackTrace();}}
控制台输出如下

到这里AIDL就通过一个简单的小例子介绍完了,由于时间仓促加之水平有限,有什么问题欢迎大家一起讨论,一起进步。
1 0
原创粉丝点击