上一篇简单介绍了AIDLhttps://blog.csdn.net/smallFish_lin/article/details/89327302
接下来我们再来看一下AIDL传递我们的自定类型的数据,aidl传递的自定义类型的数据必须实现parcelable接口
首先我们来看服务端的实现:
- 自定义一个Person类实现Parcelable接口
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
private int age;
private String name;
private boolean gender;
public Person(){}
public Person(int age, String name, boolean gender) {
this.age = age;
this.name = name;
this.gender = gender;
}
protected Person(Parcel in) {
age = in.readInt();
name = in.readString();
gender = in.readByte() != 0;
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
dest.writeInt((gender ? 1 : 0));
}
//注意,此处的读值顺序应当是和writeToParcel()方法中一致的
//为了使用定向 out 和 inout,我们需要实现readFromParcel,参数是一个Parcel用来存储和传输数据
public void readFromParcel(Parcel dest){
age = dest.readInt();
name = dest.readString();
if (dest.readInt() == 1)
gender = true;
else gender = false;
}
}
- 在上篇的aidl接口目录下创建Person.aidl,注意Person.java 和Person.aidl 的目录一定要相同
// Person.aidl
package com.xx.serverapplication;
// Declare any non-default types here with import statements
parcelable Person;
- 在服务端的aidl接口中声明方法void showPersonInfo(Person person);
package com.xx.serverapplication.aidl;
//这里需要显示的import Person 类
import com.xx.serverapplication.aidl.Person;
// Declare any non-default types here with import statements
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);
int getSum(int a, int b);
//定向Tag in--数据只能由客户端写入,在服务端修改了数据后,客户端数据不变
String showPersonInfoIn(in Person person);
//定向Tag out--数据只能由服务端传入,客户端传输数据无校,服务端对数据的修改会体现在客户端
String showPersonInfoOut(out Person person);
//定向Tag inout--数据可以由服务端传入也可以由客户端传入,数据无论在哪里改变都会体现出来
String showPersonInfoInOut(inout Person person);
}
- 在服务端的service中对void showPersonInfo(Person person)进行实现
package com.xx.serverapplication;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.xx.serverapplication.aidl.IMyAidlInterface;
import com.xx.serverapplication.aidl.Person;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return iBinder;
}
IMyAidlInterface.Stub iBinder = new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public int getSum(int a, int b) throws RemoteException {
return a + b;
}
@Override
public String showPersonInfoIn(Person person) throws RemoteException {
Log.e("showPersonInfoIn", "服务端收到; " + "server Person INFO: 姓名 : " + person.getName() + "; 年龄 : " + person.getAge() + "; 性别 :" + (person.isGender()?"女" : "男"));
person.setName("服务器修改In");
return "server Person INFO: 姓名 : " + person.getName() + "; 年龄 : " + person.getAge() + "; 性别 :" + (person.isGender()?"女" : "男");
}
@Override
public String showPersonInfoOut(Person person) throws RemoteException {
Log.e("showPersonInfoOut", "服务端收到;" + "server Person INFO: 姓名 : " + person.getName() + "; 年龄 : " + person.getAge() + "; 性别 :" + (person.isGender()?"女" : "男"));
person.setName("服务器修改Out");
return "server Person INFO: 姓名 : " + person.getName() + "; 年龄 : " + person.getAge() + "; 性别 :" + (person.isGender()?"女" : "男");
}
@Override
public String showPersonInfoInOut(Person person) throws RemoteException {
Log.e("showPersonInfoInOut", "服务端收到;" + "server Person INFO: 姓名 : " + person.getName() + "; 年龄 : " + person.getAge() + "; 性别 :" + (person.isGender()?"女" : "男"));
person.setName("服务器修改InOut");
return "server Person INFO: 姓名 : " + person.getName() + "; 年龄 : " + person.getAge() + "; 性别 :" + (person.isGender()?"女" : "男");
}
};
}
- 启动服务
- 客户创建Person类及其aidl声明, 和服务器端一样,Person.java 和Person.aidl的目录要保持一致,否则会找不到类
- 客户端进行调用
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyAidlInterface myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
Person p1 = new Person(30, "小红", true);
Person p2 = new Person(30, "小黄", true);
Person p3 = new Person(30, "小蓝", false);
Log.e("onServiceConnected", "客户端rsult = " + "server Person INFO: 姓名 : " + p1.getName() + "; 年龄 : " + p1.getAge() + "; 性别 :" + (p1.isGender()?"女" : "男"));
Log.e("onServiceConnected", "客户端rsult = " + "server Person INFO: 姓名 : " + p2.getName() + "; 年龄 : " + p2.getAge() + "; 性别 :" + (p2.isGender()?"女" : "男"));
Log.e("onServiceConnected", "客户端rsult = " + "server Person INFO: 姓名 : " + p3.getName() + "; 年龄 : " + p3.getAge() + "; 性别 :" + (p3.isGender()?"女" : "男"));
Log.e("onServiceConnected", "客户端调用服务器的showPersonInfo,rsult = " + myAidlInterface.showPersonInfoIn(p1));
Log.e("onServiceConnected", "客户端调用服务器的showPersonInfo,rsult = " + myAidlInterface.showPersonInfoOut(p2));
Log.e("onServiceConnected", "客户端调用服务器的showPersonInfo,rsult = " + myAidlInterface.showPersonInfoInOut(p3));
Log.e("onServiceConnected", " rsult = " + "server Person INFO: 姓名 : " + p1.getName() + "; 年龄 : " + p1.getAge() + "; 性别 :" + (p1.isGender()?"女" : "男"));
Log.e("onServiceConnected", " rsult = " + "server Person INFO: 姓名 : " + p2.getName() + "; 年龄 : " + p2.getAge() + "; 性别 :" + (p2.isGender()?"女" : "男"));
Log.e("onServiceConnected", " rsult = " + "server Person INFO: 姓名 : " + p3.getName() + "; 年龄 : " + p3.getAge() + "; 性别 :" + (p3.isGender()?"女" : "男"));
} catch (RemoteException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
Intent service = new Intent();
service.setAction("com.aidl.service.room");
//从 Android 5.0开始 隐式Intent绑定服务的方式已不能使用,所以这里需要设置Service所在服务端的包名
service.setPackage("com.xx.serverapplication");
bindService(service,serviceConnection, BIND_AUTO_CREATE);
结果:
通过结果我们也能很清楚的明白AIDL中的定向tag in,out, inout 的区别:
Tag in--数据只能由客户端写入,在服务端修改了数据后,客户端数据不变
Tag out--数据只能由服务端传入,客户端传输数据无校,服务端对数据的修改会体现在客户端 String
Tag inout--数据可以由服务端传入也可以由客户端传入,数据无论在哪里改变都会体现出来 String
下一篇我们会学习基于AIDL 的 Messenger 的实现
参考:https://developer.android.google.cn/guide/components/bound-services.html
https://developer.android.google.cn/guide/components/aidl.html