zoukankan      html  css  js  c++  java
  • Android进程间通信之使用AIDL

    AIDLAndroid Interface Definition Language ,可实现进程间的通信,并且允许多线程访问。(如果需要进程间通信,又不需要处理多线程访问,那么使用Messenger的方式更为合适),实现AIDL,需要以下几个步奏。

    1.定义AIDL接口

     

    AIDL接口使用后缀名为.aidl的文件来定义(例如创建一个IRemoteData.aidl),使用java语法来编写,在编译时,Android sdk工具会在/gen目录下生成一个java文件(IRemoteData.java),此文件内有一个静态内部抽象类Stub,继承了Binder类并实现了接口(IRemoteData)。它提供了一个asInterface(android.os.IBinder obj)IBinder对象转换成我们声明的接口类型(实际上就是在Service端对Stub的实现)。

     

    AIDL支持以下五种数据类型:java基本数据类型(int,char,boolean)StringCharSequenceListMap。如果你要在AIDL中使用其他数据类型,那么必须使用import导入,即使该类型和aidl处于同一包中。其次,所有非原始数据类型都必须指定参数方向,传入参数用关键字in表示,传出参数用out,传入传出参数用inout,基本数据类型都是传入值。

     

     1 package com.young.testserver.aidl;
     2 
     3 import com.young.testserver.aidl.Person;
     4 
     5 interface IRemoteData {
     6     int getRemoteData();
     7     void setRemoteData(int data);
     8     
     9     Person getPerson();
    10     void setPerson(in Person person);
    11 }

    由于该aidl文件中使用了非原始数据类型Person,所以需要创建一个aidl文件对Person进行声明

    1 package com.young.testserver.aidl;
    2 
    3 parcelable Person;

    2.创建服务端Service,将我们对AIDL接口的实现通过onBind()方法返出去。

     1 public class AidlRemoteService extends Service {
     2 
     3     // IRemoteData.Stub的具体实现
     4     private class RemoteData extends IRemoteData.Stub {
     5         int data;
     6         Person person;
     7         @Override
     8         public int getRemoteData() throws RemoteException {
     9             return data;
    10         }
    11 
    12         @Override
    13         public void setRemoteData(int data) throws RemoteException {
    14             this.data = data;
    15         }
    16 
    17         @Override
    18         public Person getPerson() throws RemoteException {
    19             return person;
    20         }
    21 
    22         @Override
    23         public void setPerson(Person person) throws RemoteException {
    24             this.person = person;
    25         }
    26 
    27     }
    28 
    29     @Override
    30     public IBinder onBind(Intent intent) {
    31         // 将实现的IRemoteData.Stub类返出去,客户端可以使用Stub提供的asInterface获得
    32         return new RemoteData();
    33     }
    34 }

    3.将服务端对应的aidl文件与java文件拷贝到客户端,在客户端绑定服务时,使用Stub类提供的asInterface获取服务端实现的接口类,然后使用这个已实现的接口类就可以调用AIDL中的函数。

     1 public class AidlClientActivity extends Activity {
     2 
     3     private static final String TAG = "--DEBUG--";
     4   
     5     private static final String BIND_ACTION = "com.young.server.START_AIDL_SERVICE";
     6     private Button mBindBtn;
     7 
     8     @Override
     9     protected void onCreate(Bundle savedInstanceState) {
    10         super.onCreate(savedInstanceState);
    11         setContentView(R.layout.activity_aidl_client);
    12 
    13         mBindBtn = (Button) findViewById(R.id.bind_service);
    14         mBindBtn.setOnClickListener(new OnClickListener() {
    15             @Override
    16             public void onClick(View v) {
    17                 bindService(new Intent(BIND_ACTION), conn, Context.BIND_AUTO_CREATE);
    18             }
    19         });
    20     }
    21 
    22     private ServiceConnection conn = new ServiceConnection() {
    23 
    24         @Override
    25         public void onServiceDisconnected(ComponentName name) {
    26             Log.v(TAG, "AIDL 服务已断开");
    27         }
    28 
    29         @Override
    30         public void onServiceConnected(ComponentName name, IBinder service) {
    31             Log.v(TAG, "AIDL 服务已链接");
    32 
    33             // 获得服务端对Stub的实现
    34             IRemoteData remoteData = IRemoteData.Stub.asInterface(service);
    35             try {
    36                 remoteData.setRemoteData(123456);
    37                 int data = remoteData.getRemoteData();
    38                 Log.v(TAG, "client get remote data=" + data);
    39 
    40                 remoteData.setPerson(new Person("Allen", 25));
    41                 Person person = remoteData.getPerson();
    42                 Log.v(TAG, "client get remote Person=" + person.toString());
    43             } catch (RemoteException e) {
    44                 e.printStackTrace();
    45             }
    46         }
    47     };
    48 }

    4.通过AIDL在进程间传递对象,需要符合以下几点要求

    (1)实现Parcelable接口。

    (2)实现writeToParcel方法,以便将当前对象状态写入Parcel中。

    (3)增加一个名为CREATOR的静态变量,实现Parcelable.Creator<T>接口

    (4)创建一个AIDL文件来声明这个类(见上文的Person.aidl)

     1 public class Person implements Parcelable {
     2     
     3     private String name;
     4     private int age;
     5     
     6     public Person(String name, int age) {
     7         super();
     8         this.name = name;
     9         this.age = age;
    10     }
    11 
    12     public String getName() {
    13         return name;
    14     }
    15 
    16     public void setName(String name) {
    17         this.name = name;
    18     }
    19 
    20     public int getAge() {
    21         return age;
    22     }
    23 
    24     public void setAge(int age) {
    25         this.age = age;
    26     }
    27 
    28     @Override
    29     public String toString() {
    30         return "Person [name=" + name + ", age=" + age + "]";
    31     }
    32 
    33     // -------------分割线---------------
    34 
    35     // 注意读入和写出顺序
    36     public Person(Parcel parcel) {
    37         name = parcel.readString();
    38         age = parcel.readInt();
    39     }
    40 
    41     public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
    42 
    43         @Override
    44         public Person createFromParcel(Parcel source) {
    45             return new Person(source);
    46         }
    47 
    48         @Override
    49         public Person[] newArray(int size) {
    50             return new Person[size];
    51         }
    52 
    53     };
    54 
    55     @Override
    56     public int describeContents() {
    57         return 0;
    58     }
    59 
    60     @Override
    61     public void writeToParcel(Parcel dest, int flags) {
    62         dest.writeString(name);
    63         dest.writeInt(age);
    64     }

    最后运行程序,打印日志结果如下,客户端取到了从客户端传给服务端的数据。

    11-13 15:56:23.081: V/--DEBUG--(25361): AIDL 服务已链接
    11-13 15:56:23.081: V/--DEBUG--(25361): client get remote data=123456
    11-13 15:56:23.081: V/--DEBUG--(25361): client get remote Person=Person [name=Allen, age=25]

  • 相关阅读:
    制作软件说明书的图片编辑工具推荐PicPick
    浅谈配网供电可靠性及管理措施
    C#的winform中MDI 父窗体改变背景色
    Windows完成端口与Linux epoll技术简介
    django中的form表单
    调整图层初识3
    PS图层混合模式详解
    图层混合模式之正片叠底、滤色
    photoshop调整图层初识1
    调整图层初识2
  • 原文地址:https://www.cnblogs.com/virtual-young/p/4095159.html
Copyright © 2011-2022 走看看