转载请注明来自:http://blog.csdn.net/ly20116/article/details/51112833

一、AIDL定义

AIDL(Android Interface Definition Language),它允许你定义客户端与服务端达成一致的程序接口使用进程间通信( interprocess communication ,IPC)相互交流。

在Android上面,一个进程不能正常的访问另一个进程的内存。 所以说,他们需要分解他们的对象为操作系统可以理解的基本单位,然后为你把这些对象按次序跨越进程边界 书写这些代码是单调冗长的,所以android使用AIDL为你处理这个问题。

AIDL IPC机制是面向接口的,它是使用代理类在客户端和实现端传递数据

注意:使用AIDL只有在你允许来自不同应用的客户端跨进程通信访问你的service,并且想要在你的service种处理多线程的时候才是必要的。

二、AIDL接口的创建与使用

你必须在一个.aidl文件中使用java编程语言语法定义你的AIDL接口,然后在提供service的应用中和任何绑定到这个service的应用中的源代码中(在src目录下)保存它

当你编译包含.aidl文件的应用时,Android SDK工具基于这个.aidl文件生成一个IBinder接口,并且把它保存到项目的gen目录吓 service必须恰当的实现这个IBinder接口 之后客户端应用可以绑定到这个服务上,然后从IBinder调用方法来执行IPC

1、创建AIDL文件

IServiceAidlInterface.aidl:

// IServiceAidlInterface.aidlpackage com.yang.serviceaidl;// Declare any non-default types here with import statementsinterface IServiceAidlInterface {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);    void setData(String data);//自定义方法声明}

默认的,AIDL支持下面数据类型

  • Java语言中的所有基本数据类型(比如int、long、char、boolean等等)
  • String
  • CharSequence
  • List

    List中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是你定义的parcelableList可以使用范型(例如,List) 接收端的实际类经常是一个ArrayList,尽管方法是使用List接口生成的
  • Map

    Map中的所有元素必须是AIDL支持的类型之一,或者是一个其他AIDL生成的接口,或者是你定义的parcelable范型map是不被支持的(比如这种形式Map) 接收端的实际类经常是一个HashMap,尽管方法是使用Map接口生成的

对于上述类型之外的类型,你必须声明 import ,即使在同一个包内

简单的保存你的.aidl文件在你工程的src目录下,当你build你的应用时,SDK工具在你工程的gen目录下生成IBinder接口文件 生成的文件名字与.aidl名字匹配,但是是以.java为扩展名(例如IRemoteService.aidl对应为IRemoteService.java)

2、实现接口
在你定义的Service中onBind方法

 @Override    public IBinder onBind(Intent intent) {        return new IServiceAidlInterface.Stub() {            @Override            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {            }            @Override            public void setData(String data) throws RemoteException {                AppService.this.data=data;            }        };    }

Stub类(如IServiceAidlInterface.Stub())是它父类的抽象实现,并且声明了.aidl中所有的方法,
Stub的asInterface()方法,它是用来接收一个IBinder(通常IBinder传递给客户端的onServiceConnected()回调方法)并且返回一个Stub接口的实例。

注意事项:

  • 调用不保证在主线程中执行
  • 默认的,RPC调用是同步的。 如果你知道service需要花费一些时间来完成请求,你就不应该从activity的主线程中调用它,因为它可能使得应用没有响应(Android也许会显示一个ANR的对话框),通常你应该在客户端中一个单独的线程调用它
  • 抛出的异常不会返回给调用者

    3、客户端获取接口

如果是跨应用调用Service,那么你应该在另一个应用中一模一样的AIDL文件(包名,类名相同等等),。如下图结构:

在androidapp工程中建立一个与app工程相同的AIDL文件,包括包名。
跨应用启动Service的Intent(显示调用方法);

Intent serviceIntent=new Intent();serviceIntent.setComponent(new ComponentName("com.yang.serviceaidl","com.yang.serviceaidl.AppService"));参数说明: 1. 包名 2. 类名//启动服务   startService(serviceIntent);//关闭服务  stopService(serviceIntent);//绑定服务   bindService(serviceIntent,this,Context.BIND_AUTO_CREATE);//解绑服务    unbindService(this);   

在androidapp中调用给接口,在MainActivity(实现了ServiceConnection接口)中onServiceConnected()方法中

 private IServiceAidlInterface binder=null;  @Override    public void onServiceConnected(ComponentName name, IBinder service) {//        binder= (IServiceAidlInterface) service;  //错误的        binder=IServiceAidlInterface.Stub.asInterface(service);    }

类似于Service的绑定通信。

传递数据

if(binder!=null){           try {                       binder.setData(data.getText().toString());               } catch (RemoteException e) {                        e.printStackTrace();               } }

总结:调用IPC方法步骤:

  1. 在项目中的src目录下面导入.aidl文件
  2. 声明一个IBinder接口(基于AIDL生成的)的实例
  3. 实现ServiceConnection
  4. 调用Context.bindService(),传递到你的ServiceConnection实现中
  5. 在你的onServiceConnected()实现中,你会收到一个IBinder实例(称为服务端) 调用YourInterfaceName.Stub.asInterface((IBinder)service)把返回值映射到YourInterface类型上面
  6. 调用你接口中定义的方法 你应该捕获当连接损坏时抛出的DeadObjectException异常,这是远程方法唯一会抛出的异常
  7. 使用你接口的实例调用Context.unbindService()来断开连接

三、跨进程传递对象

果你想通过IPC接口把一个类从一个进程传递到另一个进程中,那么是可以的。 然而,你必须保证为你的类而写的代码也是对IPC通道另一端是可用的,并且你的类必须支持Parcelable接口 支持Parcelable接口是很重要的,因为它允许Android系统把对象分解为可以被组织跨进程传输基本单元

为了建立一个支持Parcelable协议的类,你必须遵守下面的规则:

  1. 要实现Parcelable接口
  2. 实现writeToParcel,它是用来把对象的当前状态写入到一个Parcel对象中的。
  3. 在你的类中添加一个叫CREATOR的静态域,它要实现Parcelable.Creator接口
  4. 最后,建立一个.aidl文件声明你的parcelable类(如下面的Rect.aidl所示)
    如果你使用一个定制的构建过程,不要构建.aidl文件。与C语言中的头文件类似,.aidl文件不会被编译

AIDL使用代码中的这些域和方法封装传送和解读你的对象

Rect.aidl文件:

package android.graphics;// Declare Rect so AIDL can find it and knows that it implements// the parcelable protocol.parcelable Rect;

Rect类:

public final class Rect implements Parcelable {    public int left;    public int top;    public int right;    public int bottom;    public static final Parcelable.Creator CREATOR = newParcelable.Creator() {        public Rect createFromParcel(Parcel in) {            return new Rect(in);        }        public Rect[] newArray(int size) {            return new Rect[size];        }    };    public Rect() {    }    private Rect(Parcel in) {        readFromParcel(in);    }    public void writeToParcel(Parcel out) {        out.writeInt(left);        out.writeInt(top);        out.writeInt(right);        out.writeInt(bottom);    }    public void readFromParcel(Parcel in) {        left = in.readInt();        top = in.readInt();        right = in.readInt();        bottom = in.readInt();    }}

总结

AIDL是android接口定义语言,主要是android中用来解决进程间通信(interprocess communication ,IPC)的。
它和绑定服务通信实现类似,不过是绑定服务通信时我们继承Binder实现的接口MyBinder变成了AIDL实现。

AIDL实例下载链接

更多相关文章

  1. Fragment的交互及管理
  2. android实时高斯模糊
  3. Android(安卓)Studio的.gitignore以及gitignore无效的解决
  4. Android:不同drawable文件夹的区别
  5. (OK) 编译batman-adv.ko—成功—android—cm11源码—下载
  6. Android(安卓)利用服务Service创建标题栏通知
  7. 《Android应用开发揭秘》读者问题汇总
  8. Android(安卓)检测是否有ROOT权限
  9. Android之Broadcast, BroadcastReceiver(广播)

随机推荐

  1. Android base64 上传图片
  2. Android Studio第六期 - 横向GridView
  3. android的k歌
  4. Android--遍历SQLite数据库下的所有表名
  5. EditText
  6. Android--取得布局中指定控件的宽高
  7. Android取得系统信息和分辨率内存信息
  8. 删除android ScrollView边界阴影方法
  9. Android ListView二三事
  10. Android_linux下android platforms下载地