简述:
Android 接口定义语言 AIDL(Android Interface Definition Language)与其他已有的 IDL 很类似。 客户端和服务端可以通过由它定义的编程接口来达成共识,以便通过进程间通讯(IPC)完成相互通讯。 在 Android 系统中,通常一个进程不允许直接访问另一个进程的内存。 因此为了能够实现对话,进程需要把对象分解为操作系统可以识别的原生数据,在跨越进程边界后再组装起来。 实现组装的代码非常枯燥无趣,因此 Android 通过 AIDL 可有助于完成这一过程。
AIDL的创建:
1、利用AS创建AIDL十分的方便,首先光标移至项目上,然后右键new-->AIDL-->AIDL File,点击确定。
2、填写自定义AIDL文件的编写,点击Finish。
OK,至此AIDL的基本创建工作已经完成,接下来我们看看AIDL编写。
AIDL的语法规则:
1、AIDL支持的”四种“数据类型
① Java编程语言的基本数据类型 (byte、short、int, long,float、double、char, boolean共八种);
② Java语言中的String、List、Map和CharSequence;
③ 其他的AIDL生成的interface;
④ 实现了Parcelable接口的自定义类。
⭐️注意:
① 在使用AIDL的第一类和第二类数据类型时,不需要import类。
② 在使用第二类数据类型时List的泛型必须为Java的基本数据类型或者上述的第四种数据类型,但是Map中的所有数据只能是这里列出的类型、其他某个基于 AIDL 生成的接口、已声明的自定义 Parcelable 类。 这里不支持 Map 泛型(比如 Map<String,Integer> 的形式)。 虽然方法是通过 Map 接口生成的,但实际收到的实体类其实会是一个 HashMap。
③ 如果需要在AIDL中使用其他AIDL接口类型(也就是第三中数据类型),需要import,即使是在相同包结构下。
④ 使用第四种数据类型时也就是使用了自定义类,那么该类必须实现Parcelable接口,其次该类在被AIDL中被引用时必须import,即使是在相同包结构下。
2、AIDL文件方法参数方向问题
① 方法可以有多个参数,也可以不带参数;可有一个返回值,或无返回值(void)。
② 所有非简单类型的参数都需要带有一个指明数据方向的标志。 可以是in、out或inout(in表示由客户端设置,out表示由服务端设置,inout是两者均可设置)。
3、自定义类型数据的通讯
在实际的开发中可能我们大多数情况下会使用第四种数据类型,那么本文将以第四种数据类型为例下一个小的案例。
案例
首先我们创建一个AIDL文件(见上述情况,这里不再书写),然后创建一个自定义类,创建自定义类需要有特别注意的地方,不然会报出“import class XXX not found”异常。为了出现这个问题,
1、 我们创建的自定义的实体类放在aidl文件下,同时注意该实体类一定要实现序列化Parcelabe接口,详见Parcelable接口的使用
2、 创建自定义实体类对应的AIDL文件,文件中的内容包括包名和“parcelable 类名”(注意parcelable首字母小写)
LocationInfo.java代码如下:
import android.os.Parcel;
import android.os.Parcelable;
/**
* 类描述:
* Created by lizhenya on 16/9/4.
*/
public class LocationInfo implements Parcelable{
private double longitude;
private double latitude;
private String locationName;
public LocationInfo() {
}
public LocationInfo(double longitude, String locationName, double latitude) {
this.longitude = longitude;
this.locationName = locationName;
this.latitude = latitude;
}
protected LocationInfo(Parcel in) {
longitude = in.readDouble();
latitude = in.readDouble();
locationName = in.readString();
}
public static final Creator<LocationInfo> CREATOR = new Creator<LocationInfo>() {
@Override
public LocationInfo createFromParcel(Parcel in) {
return new LocationInfo(in);
}
@Override
public LocationInfo[] newArray(int size) {
return new LocationInfo[size];
}
};
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
@Override
public String toString() {
return "LocationInfo{" +
"longitude=" + longitude +
", latitude=" + latitude +
", locationName='" + locationName + '\'' +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeDouble(longitude);
parcel.writeDouble(latitude);
parcel.writeString(locationName);
}
}
3、上述任务完成之后我们开始编写住.AIDL接口中的方法。主要import和参数的方向(in、out和inout)
如下图所示:
4、上述AIDL接口算是完成了书写,下面我们书写一个远程Service测试一下:
代码如下:
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
/**
* 类描述:
* Created by lizhenya on 16/9/4.
*/
public class LocationService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
class LocationInterface extends MyLocationInterface.Stub {
}
}
这个过程中会遇到 MyLocationInterface.Stub找不到问题,直接rebuild一下就OK了。解决问题后的代码如下:
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
/**
* 类描述:
* Created by lizhenya on 16/9/4.
*/
public class LocationService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
class LocationInterface extends MyLocationInterface.Stub {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public LocationInfo getLocation() throws RemoteException {
return null;
}
@Override
public void setLocationInfo(LocationInfo locationInfo) throws RemoteException {
}
}
}
如果自定义类型的数据有问题上述代码出现错误甚至不会出现上述代码。
OK,AIDL的应用就介绍到这里了,日后遇到问题再加入。