您的位置:首页 > 大数据 > 人工智能

AIDL的理解与使用详解

2017-01-16 17:17 239 查看
   
本篇文章将对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]把我们定义的中间人对象返回
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}

//在服务里面定义一个方法

public void testMethod(){
System.out.println("我是远程服务里面的方法");
}

//[1]定义中间人对象
private class MyBinder extends Binder implements Iservice{

//调用testMethod方法
@Override
public 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();
//设置一个action
intent.setAction("com.itft.remoteservice");//随便定义即可
MyConn conn = new MyConn();
//[2]目的是为了获取我们定义的中间人对象
bindService(intent, conn, BIND_AUTO_CREATE);

然后我们应该在本地服务中去获取远程服务中的中间人对象(MyBinder),现在关键问题来了,在本地服务中无法获取远程服务中的中间人对象,———》》》》AIDL的用处来了!
//监视服务的状态
private class MyConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取中间人对象
iservice = Stub.asInterface(service);
}
@Override
public 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方法
@Override
public 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 {

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 获取中间人对象
iservice = Stub.asInterface(service);
}

@Override
public void onServiceDisconnected(ComponentName name) {

}

}
此时AIDL服务构建完成,可以通过AIDL来调用远程服务中的方法了
public void click(View v) {
try {
iservice.callTestMethod();//调用代码
} catch (RemoteException e) {
e.printStackTrace();
}
}
控制台输出如下



到这里AIDL就通过一个简单的小例子介绍完了,由于时间仓促加之水平有限,有什么问题欢迎大家一起讨论,一起进步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 移动开发 aidl