AIDL进行进程间通讯
AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言
在上一篇 使用Messenger进行跨应用(进程)通讯中,使用Messenger进行进程间通讯的时候,服务端是能一个个的处理客户端的请求,如果有大量的并发请求的时候,Messenger就不适用了.并且Messenegr只能传递消息,并不能跨进程调用服务端的方法,这时候可以使用AIDL来实现跨进程调用服务端的方法.
AIDL持的数据类型包括:
-
java的8种基本数据类型byte,short,int,long,float,double,boolean,char
-
String和CharSequence
-
List:只支持ArrayList.List种的元素必须是AIDL支持的数据类型
-
Map:只支持HashMap,.Map的元素必须是AIDL支持的数据类型
-
Parcelable:实现了Parcelable接口的 对象
-
AIDL:所有的AIDL接口本身也可以在AIDL文件中使用.
当AIDL使用类型是Parcelable时必须导包,即使Parcelable和AIDL在同一包内.另外在AIDL中,除了基本数据类型,其他类型的参数必须加上定向TAG,in out或者inout,in表示输入型参数,out表示输出型参数,inout表示输入输出型参数,我们要根剧实际情况来使用TAG,不能忙盲目的使用inout,因为在底层是有开销的.
为了开发方便,建议把所有跟AIDL有关的文件都放在同一包内,当客户端和服务端是两个不同的应用时,需要把AIDL的相关的文件全部复制到客服端内.放在一个包内不容易出错.
服务端的实现
要实现的简单的功能,服务端有两个方法,可以向List 中addPerson,也可以获取List中获取全部的Person
-
编写AIDL文件
使用Android Studio编写AIDL文件
然后会在Android Studio会在src/main下 会自动创建一个aidl文件夹.然后把所有跟AIDL有关的文件都创建在这个包下.
-
因为Person类不是AIDL支持的基本数据类型,所以要实现Parcelable接口
public class Person implements Parcelable { private String name; public Person(Parcel in) { name = in.readString(); } 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]; } }; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); } }
-
因为Person类实现了Parcelable,所以要创建一个Person.aidl
// Book.aidl package com.lixxy.service; // Declare any non-default types here with import statements parcelable Person;
-
最后编写IPersonAidl.aidl.因为服务端有两个方法,所以IPersonAidl.aidl也要定义相同方法
// IBookAidl.aidl package com.lixxy.service; import com.lixxy.service.Person; interface IPersonAidl { List<Person> getList(); void addPerson(in Person person); }
编写完ADIL以后还需要在bulid.gradle android{}中加入
sourceSets {
main {
java.srcDirs = ['src/main/java', 'src/main/aidl']
}
}
因为Android Studio自动生成的AIDL文件夹与java文件夹包名一致,为了使编译器能找到Person类,所以要加上,不然会报错
AIDL相关的文件编写完成后需要Make Project,Android Studio会自动为我们生成IPersonAidl.java 接口
- 编写PersonService
public class PersonManagerService extends Service {
@Override
public void onCreate() {
super.onCreate();
Person person = new Person();
person.setName("小红");
mPeople.add(person);
}
public static final String TAG = "=========>";
//包含Person对象的list
private List<Person> mPeople = new ArrayList<>();
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "绑定成功");
return mBinder;
}
private Binder mBinder = new IPersonAidl.Stub() {
@Override
public List<Person> getList() throws RemoteException {
return mPeople;
}
@Override
public void addPerson(Person person) throws RemoteException {
mPeople.add(person);
}
};
}
然后需要在AndroidManifest中声名PersonManagerService
<service
android:name=".PersonManagerService"
android:exported="true">
</service>
客户端的实现
首先先创建AIDL文件夹,然后在AIDL文件夹下创建于服务端相同的包,然后把服务端AIDL文件夹下所有的问价都复制过来
然后Make Project,自动生成文件.
最后编写Activity
package com.lixxy.aidldemo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.lixxy.service.Person;
import com.lixxy.service.IPersonAidl;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "===>";
private IPersonAidl mIBookAidl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Intent intent = new Intent();
intent.setComponent(new ComponentName("com.lixxy.service", "com.lixxy.service.PersonManagerService"));
Button button = findViewById(R.id.mBtnBind);
Button get = findViewById(R.id.mBtnGet);
Button add = findViewById(R.id.mBtnAdd);
final TextView name = findViewById(R.id.mTvName);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
});
get.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
List<Person> list = mIBookAidl.getList();
StringBuilder builder = new StringBuilder();
for (Person person : list) {
builder.append(person.getName());
}
name.setText(builder.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Person person = new Person();
person.setName("小明");
try {
mIBookAidl.addPerson(person);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIBookAidl = IPersonAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG,"连接失败");
}
};
}
最后附上项目地址:https://github.com/Lillls/AidlDemo