最近有使用商米v2的打印机功能,涉及到AIDL,所以这篇简单讲解下 AIDL ,最后附上打印机代码。
顾名思义AIDL全称是Android Interface Definition Language
Android中一个进程通常无法访问另一个进程的内存,这时候可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口. 当然AIDL的目的不仅仅是为了实现进程间通信,尤其是在涉及多进程并发情况下的进程间通信。
服务端部分
1:创建.aidl文件
创建服务端项目后,在main下新建aidl文件夹,用于存放我们用到的aidl文件。
这里以Android studio为例:
我们可以直接右键新建aidl文件如下:
新建的aidl文件,会默认添加个方法用于演示一些基本数据类型,如下图所示:
AIDL 使用简单语法,使您能通过可带参数和返回值的一个或多个方法来声明接口。 参数和返回值可以是任意类型,甚至可以是其他 AIDL 生成的接口。
每个 .aidl 文件都必须定义单个接口,并且只需包含接口声明和方法签名。
默认情况下,AIDL 支持下列数据类型:
1:Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
2:String
3:CharSequence
4:List
List 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 可选择将 List 用作“通用”类(例如,List)。另一端实际接收的具体类始终是 ArrayList,但生成的方法使用的是 List 接口。
5:Map
Map 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 不支持通用 Map(如 Map<String,Integer> 形式的 Map)。 另一端实际接收的具体类始终是 HashMap,但生成的方法使用的是 Map 接口。
除了以上列出的类型外,我们必须为每个附加类型加入一个 import 语句,即使这些类型是在与接口相同的软件包中定义。
另外定义接口时,我们需要注意以下几点:
1:方法可带零个或多个参数,返回值或空值。
2:所有非上述类型的参数都需要指示数据走向的方向标记。可以是 in、out 或 inout。
上述参数默认为 in,不能是其他方向。
3:.aidl 文件中包括的所有代码注释都包含在生成的 IBinder 接口中(import 和 package 语句之前的注释除外)
4:只支持方法;不能公开 AIDL 中的静态字段。
非原参类型定义方法,即我们通常定义的bean类,
创建java文件定义参数,实现Parcelable接口,自动导入对应的接口方法。
package com.zh.server;
import android.os.Parcel;
import android.os.Parcelable;
/**
* create by zj on 2019/6/4
*/
public class People implements Parcelable {
public int sno;
public String name;
public int sex;
public int age;
protected People(Parcel in) {
sno = in.readInt();
name = in.readString();
sex = in.readInt();
age = in.readInt();
}
public static final Creator<People> CREATOR = new Creator<People>() {
@Override
public People createFromParcel(Parcel in) {
return new People(in);
}
@Override
public People[] newArray(int size) {
return new People[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(sno);
dest.writeString(name);
dest.writeInt(sex);
dest.writeInt(age);
}
}
接着在aidl文件夹下生产同名的people.aidl文件。
内容十分简单:
package com.zh.server;
parcelable People;
注意:parcelable 是小写
package com.zh.server;
// Declare any non-default types here with import statements
import com.zh.server.People;
interface IMyAidlInterface {
/**
* 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);
List<People> getPeople();
void addPeople(in People people);
}
添加自定义的类型参数,import必须导入全路径。
添加获取对象集合以及添加对象的方法
2:实现接口
添加java文件继承service;
package com.zh.server;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* create by zj on 2019/6/4
*/
public class MyService extends Service {
private List<People> peopleList = new ArrayList<People>();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private IMyAidlInterface.Stub mBinder=new IMyAidlInterface.Stub() {
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString){
}
@Override
public List<People> getPeople() throws RemoteException {
synchronized (peopleList) {
return peopleList;
}
}
@Override
public void addPeople(People people) throws RemoteException {
synchronized (peopleList) {
if (!peopleList.contains(people)) {
peopleList.add(people);
}
}
}
};
}
3:Service定义
<service android:name=".MyService" >
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="com.zh.server.MyService" />
</intent-filter>
</service>
截止这里服务端的代码已经完成,接下来我们可以编写调用的代码了。
客户端代码
1:拷贝aidl文件
将服务端的aidl连同文件目录拷贝到main的aidl目录下。
当然,因为有自定义对象参数的问题,所以我们需要复制bean类,
aidl中bean的导入路径也需要修改。
2:调用相关
首先定义ServiceConnection:
private ServiceConnection serviceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myAidlInterface=IMyAidlInterface.Stub.asInterface(service);
try {
List<People> list=myAidlInterface.getPeople();
StringBuilder sb=new StringBuilder();
for (int i=0;i<list.size();i++){
sb.append(list.get(i).name+"\n");
}
//数据展示
binding.tvInfo.setText(sb.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
myAidlInterface=null;
}
};
接着就是bindservice
Intent intentService = new Intent();
intentService.setPackage("com.zh.server");
intentService.setAction("com.zh.server.MyService");
MainActivity.this.bindService(intentService, serviceConnection, BIND_AUTO_CREATE);
看下效果: