aidl :Android Interface Definition Language,即Android接口定义语言
首先我们服务端需要创建一个Service来监听客户端的连接,然后创建一个aidl文件,将暴露给客户端的接口在这个aidl中声明,最后在Service中实现这些接口.
在客户端就是bind服务端的Servcie,然后将返回的Binder对象转换为aidl接口的类型,然后就能调用aidl的方法了.
AIDL中支持的数据类型:
Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
List:在List中的所有元素必须以上列表中支持的数据类型之一,或者其他 AIDL 生成的接口或自定义序列化的类型之一。可选择将List用作“通用”类(例如,List)。虽然方法生成使用的是List接口,但实际上其他端接收到的类总是ArrayList。
Map:在Map中的所有元素必须以上列表中支持的数据类型之一,或者其他 AIDL 生成的接口或自定义序列化的类型之一。不支持通用 Map(如 Map 形式的 Map)。虽然方法生成使用的是Map接口,但实际上其他端接收到的类总是HashMap。
Parcelable :实现了Parcelable接口的对象
AIDL:所有的AIDL接口本身也可以在AIDL中使用
- AIDL中除了基本数据类型,其他类型的参数都必须标上方向in,out ,inout
- AIDL中只支持方法,不支持声明静态常量
接下来我们就一步步的来使用AIDL
-
准备工作(创建Picture类)
public class Picture implements Parcelable {
public int id;
public String url;
public String name;
public Picture(int id, String url, String name) {
this.id = id;
this.url = url;
this.name = name;
}
protected Picture(Parcel in) {
this.id = in.readInt();
this.url = in.readString();
this.name = in.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.url);
dest.writeString(this.name);
}
public static final Parcelable.Creator<Picture> CREATOR = new Parcelable.Creator<Picture>() {
@Override
public Picture createFromParcel(Parcel source) {
return new Picture(source);
}
@Override
public Picture[] newArray(int size) {
return new Picture[size];
}
};
@Override
public String toString() {
return "Picture{" +
"id=" + id +
", url='" + url + '\'' +
", name='" + name + '\'' +
'}';
}
}
-
第一步创建aidl文件
// IPictureManager.aidl
package com.wsw.bindertest;
// Declare any non-default types here with import statements
import com.wsw.bindertest.picture.Picture;
interface IPictureManager {
List<Picture> getPictures();
void addPicture(in Picture picture);
}
这里需要注意的是,AIDL中使用到了的自定义类,必须为实现了Parcelable接口的类,如这里的:Picture
在创建好文件后,写入需要调用的方法,之后进行build,会发现系统自动生成了一个java文件,路径为:app\build\generated\source\aidl\debug\com\wsw\bindertest\IPictureManager.java
-
第二步服务的实现
public class PictureService extends Service {
private static final String TAG = "PictureService";
private CopyOnWriteArrayList<Picture> mPictureList = new CopyOnWriteArrayList<>();
IPictureManager mBinder = new IPictureManager.Stub() {
@Override
public List<Picture> getPictures() throws RemoteException {
SystemClock.sleep(5000);
Log.i(TAG, "getPictures: "+Thread.currentThread().getName());
return mPictureList;
}
@Override
public void addPicture(Picture picture) throws RemoteException {
Log.i(TAG, "addPicture: "+Thread.currentThread().getName());
mPictureList.add(picture);
}
};
@Override
public void onCreate() {
mPictureList.add(new Picture(1, "url1", "四川"));
mPictureList.add(new Picture(1, "url1", "湖北"));
super.onCreate();
}
public PictureService() {
}
@Override
public IBinder onBind(Intent intent) {
return mBinder.asBinder();
}
}
这里在xml中需要注册此服务,同时因为是模拟不同进程之间的通信,所以需要指定android:process属性,让次service与activity运行于不同的进程
<service android:name=".picture.PictureService"
android:process=":remote">
</service>
-
第三步客户端的实现
public class PictureManagerActivity extends AppCompatActivity {
private IPictureManager remote = null;
private static final String TAG = "PictureManagerActivity";
ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected: " + Thread.currentThread().getName());
IPictureManager pictureManager = IPictureManager.Stub.asInterface(service);
try {
remote = pictureManager;
List<Picture> pictureList = pictureManager.getPictures();
Log.d(TAG, "pictureList" + pictureList);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_picture_manager);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
remote.addPicture(new Picture(3, "11", "西藏"));
List<Picture> lists = remote.getPictures();
Log.d(TAG, "new Picture List is:" + lists);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
Intent intent = new Intent(this, PictureService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
}
这样一个简单的aidl的使用就完成了.