AIDL应用与应用间的通信(上)
2016-02-29 11:51
495 查看
AIDL作用
在Android平台,每个应用程序App都运行在自己的进程空间。通常,一个进程不能访问另一个进程的空间,即一个应用不能访问另一个应用,如果需要这中需求,需要将对象分解成操作系统可以理解的基本单元,Android提供AIDL来处理。
什么是AIDL
AIDL(Android Interface Definition Lanaguage), 是一种IDL语言,用于生成可以在Android设备上两个进程间通信的代码。如果在一个进程里要调用另 一个进程中对象的操作,就可以用使用AIDL生成可序列化的参数。通俗点,就是在一个进程中的Activity要调用另一个进程中的Service的操作,就可以使用AIDL生成可序列化的参数。
同一个App应用的Activity与Service也可以在不同的进程里,可以设置Service配置,android:process=”:remote”
定义AIDL接口
AIDL接口文件,和普通的接口内容没有什么区别,只是它的扩展名为.aidl,保存在src/main目录下。如果其他应用程序需要IPC,则哪些应用程序的src/main也要带有这个.aidl文件。Android SDK tools就会在gen目录自动生成一个IBinder接口文件。Service必须适当地实现这个IBinder接口。那么客户端程序就能绑定到这个service并在IPC时从IBinder调用方法。
每个aidl文件只能定义一个接口,而且只能是接口的声明和方法的声明。
接下来讲解使用AIDL:服务端实现
1. 创建.aidl文件
AIDL 使用简单的语法来声明接口,描叙其方法以及方法的参数和返回值。这些参数和返回值可以是任意类型,甚至是其他AIDL生成的接口。
其中,基本数据类型(int , long, char, boolean等), String和CharSequence,集合接口类型List和Map,不需要import语句。
如果需要在AIDL中使用其他AIDL接口类型, 需要import,即使在相同包结构下。AIDL允许传递实现Parcelable接口的类,需要import。
特别需要注意:对于非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout, in表示客户端设置,out表示由服务器端设置,inout两者都可设置。
AIDL只支持接口方法,不能公开static变量。
例如(IMyService.aidl):
2.实现接口:
创建一个类实现刚才那个aidl的接口:
这里会看到有一个名为IMyService.Stub类,查看aidl文件生成的Java文件源代码就能发现有这么一段代码:
原来Stub类就是继承于Binder类,也就是说RemoteService类和普通的Service类没什么不同,只是所返回的IBinder对象比较特别,是一个实现了AIDL接口的Binder。
接下来就是关于所传递的数据Bean——Person类,是一个序列化的类,这里使用Parcelable接口来序列化,是Android提供的一个比Serializable 效率更高的序列化类。
Parcelable需要实现三个函数:
1) void writeToParcel(Parcel dest, int flags) 将需要序列化存储的数据写入外部提供的Parcel对象dest。读取Parcel数据的次序要和这里的write次序一致,否则可能会读错数据。
2) describeContents() 直接返回0也可以
3) static final Parcelable.Creator对象CREATOR 这个CREATOR命名是固定的,而它对应的接口有两个方法:
createFromParcel(Parcel source) 实现从source创建出JavaBean实例的功能
newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。
然后创建Person.aidl文件,**注意这里的**parcelable和原来实现的Parcelable 接口,开头的字母p一个小写一个大写:
对于实现AIDL接口,官方还提醒我们:
调用者是不能保证在主线程执行的,所以从一调用的开始就需要考虑多线程处理,以及确保线程安全;
IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。也就是IPC调用会挂起应用程序导致界面失去响应,这种情况应该考虑单独开启一个线程来处理。
抛出的异常是不能返回给调用者(跨进程抛异常处理是不可取的)
下一篇将讲解AIDL客户端的实现
在Android平台,每个应用程序App都运行在自己的进程空间。通常,一个进程不能访问另一个进程的空间,即一个应用不能访问另一个应用,如果需要这中需求,需要将对象分解成操作系统可以理解的基本单元,Android提供AIDL来处理。
什么是AIDL
AIDL(Android Interface Definition Lanaguage), 是一种IDL语言,用于生成可以在Android设备上两个进程间通信的代码。如果在一个进程里要调用另 一个进程中对象的操作,就可以用使用AIDL生成可序列化的参数。通俗点,就是在一个进程中的Activity要调用另一个进程中的Service的操作,就可以使用AIDL生成可序列化的参数。
同一个App应用的Activity与Service也可以在不同的进程里,可以设置Service配置,android:process=”:remote”
定义AIDL接口
AIDL接口文件,和普通的接口内容没有什么区别,只是它的扩展名为.aidl,保存在src/main目录下。如果其他应用程序需要IPC,则哪些应用程序的src/main也要带有这个.aidl文件。Android SDK tools就会在gen目录自动生成一个IBinder接口文件。Service必须适当地实现这个IBinder接口。那么客户端程序就能绑定到这个service并在IPC时从IBinder调用方法。
每个aidl文件只能定义一个接口,而且只能是接口的声明和方法的声明。
接下来讲解使用AIDL:服务端实现
1. 创建.aidl文件
AIDL 使用简单的语法来声明接口,描叙其方法以及方法的参数和返回值。这些参数和返回值可以是任意类型,甚至是其他AIDL生成的接口。
其中,基本数据类型(int , long, char, boolean等), String和CharSequence,集合接口类型List和Map,不需要import语句。
如果需要在AIDL中使用其他AIDL接口类型, 需要import,即使在相同包结构下。AIDL允许传递实现Parcelable接口的类,需要import。
特别需要注意:对于非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout, in表示客户端设置,out表示由服务器端设置,inout两者都可设置。
AIDL只支持接口方法,不能公开static变量。
例如(IMyService.aidl):
package com.demo; import com.demo.Person; interface IMyService { void savePersonInfo(in Person person); List<Person> getAllPerson(); }
2.实现接口:
创建一个类实现刚才那个aidl的接口:
public class RemoteService extends Service { private LinkedList<Person> personList = new LinkedList<Person>(); @Override public IBinder onBind(Intent intent) { return mBinder; } private final IMyService.Stub mBinder = new IMyService.Stub(){ @Override public void savePersonInfo(Person person) throws RemoteException { if (person != null){ personList.add(person); } } @Override public List<Person> getAllPerson() throws RemoteException { return personList; } }; }
这里会看到有一个名为IMyService.Stub类,查看aidl文件生成的Java文件源代码就能发现有这么一段代码:
/** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.demo.IMyService
原来Stub类就是继承于Binder类,也就是说RemoteService类和普通的Service类没什么不同,只是所返回的IBinder对象比较特别,是一个实现了AIDL接口的Binder。
接下来就是关于所传递的数据Bean——Person类,是一个序列化的类,这里使用Parcelable接口来序列化,是Android提供的一个比Serializable 效率更高的序列化类。
Parcelable需要实现三个函数:
1) void writeToParcel(Parcel dest, int flags) 将需要序列化存储的数据写入外部提供的Parcel对象dest。读取Parcel数据的次序要和这里的write次序一致,否则可能会读错数据。
2) describeContents() 直接返回0也可以
3) static final Parcelable.Creator对象CREATOR 这个CREATOR命名是固定的,而它对应的接口有两个方法:
createFromParcel(Parcel source) 实现从source创建出JavaBean实例的功能
newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。
public class Person implements Parcelable { private String name; private String telNumber; private int age; public Person() {} public Person(Parcel pl){ name = pl.readString(); telNumber = pl.readString(); age = pl.readInt(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getTelNumber() { return telNumber; } public void setTelNumber(String telNumber) { this.telNumber = telNumber; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeString(telNumber); dest.writeInt(age); } public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() { @Override public Person createFromParcel(Parcel source) { return new Person(source); } @Override public Person[] newArray(int size) { return new Person[size]; } }; }
然后创建Person.aidl文件,**注意这里的**parcelable和原来实现的Parcelable 接口,开头的字母p一个小写一个大写:
package com.demo; parcelable Person;
对于实现AIDL接口,官方还提醒我们:
调用者是不能保证在主线程执行的,所以从一调用的开始就需要考虑多线程处理,以及确保线程安全;
IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。也就是IPC调用会挂起应用程序导致界面失去响应,这种情况应该考虑单独开启一个线程来处理。
抛出的异常是不能返回给调用者(跨进程抛异常处理是不可取的)
下一篇将讲解AIDL客户端的实现
相关文章推荐
- 五子棋AI算法第六篇-迭代加深
- SAS MA Daily Purge
- Unable to connect to the MKS : Failed to connect to server XXXXXX:903
- email-3.1.3 交叉编译
- INSTALL_FAILED_SHARED_USER_INCOMPATIBLE错误解决
- http://blog.csdn.net/vipzjyno1/article/details/22098621
- ZOJ-3781-Paint the Grid Reloaded【11th浙江省赛】【连通块缩点】【spfa】【好题】
- wait and waitpid
- CodeForces 547E Mike and Friends [Fail树+树状数组]
- Painter's Problem
- 1014. Waiting in Line (30)
- HDU 2476 String painter
- 服饰行业淘宝商城店铺首页设计报告-转载自http://bbs.paidai.com/topic/88363
- 8VC Venture Cup 2016 - Final Round (Div. 2 Edition) D635 - Factory Repairs 线段树
- ice版本resize 错误调试(Host key verification failed)
- ice版本resize 错误调试(Host key verification failed)
- nginx socket() failed (24: Too many open files)
- WPF中的DataGrid的RowDetail显示问题
- Canvas和paint常用属性
- 机场(Airport,Seoul 2009,LA 4725)