在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作。
AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
定义AIDL接口
AIDL接口文件,和普通的接口内容没有什么特别,只是它的扩展名为.aidl。保存在src目录下。如果其他应用程序需要IPC,则那些应用程序的src也要带有这个文件。Android SDK tools就会在gen目录自动生成一个IBinder接口文件。service必须适当地实现这个IBinder接口。那么客户端程序就能绑定这个service并在IPC时从IBinder调用方法。
注意:每个aidl文件只能定义一个接口,而且只能是接口的声明和方法的声明。
我们举例说明:首先我们做一个在一个项目里开启多进程的例子。
1.项目工程列表如下:
MainActivity是运行在主进程的,ProcessService是运行在另一个进程中(实现方式看我的博客 Android 多进程基础)。
2.实现.aidl文件
接口描述文件
a、导入的包名
b、如果有使用Object对象,需要该对象 implement Parcelable 接口,并且需要导入该接口包名+类名;
如果是primitive type 不需要这步。
c、定义方法名称。
d、所有的.aidl文件已经需要传递的对象接口需要在Service 与Client中各一份
IStockService.aidl文件
package com.example.processtest.aidl;
import com.example.processtest.aidl.Person;
interface IStockService {
double getResult(double a,double b);
com.example.processtest.aidl.Person getPerson();
}
如果aidl文件中需要传递Object对象,需要添加对应的.aidl文件
Person.aidl文件
a、定义该对象Data,并实现Parcelable
b、添加Data.aidl文件,并采用如下方式编写导入Data
c、需要在服务端和 客户端都添加 Data.aidl与 Data.java文件 并且需要一致。
package com.example.processtest.aidl;
parcelable Person;
添加 对应的Object类,并且实现Parcelable接口
public class Person implements Parcelable {
private String name;
private String age;
public Person(){
}
private Person(Parcel in){
readFromParcel(in);
}
public void readFromParcel(Parcel in)
{
name = in.readString();
age = in.readString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public static final Parcelable.Creator<Person> CREATOR=new Parcelable.Creator<Person>() {
@Override
public Person createFromParcel(Parcel source) {
// TODO 自动生成的方法存根
return new Person(source);
}
@Override
public Person[] newArray(int size) {
// TODO 自动生成的方法存根
return new Person[size];
}
};
@Override
public int describeContents() {
// TODO 自动生成的方法存根
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO 自动生成的方法存根
dest.writeString(name);
dest.writeString(age);
}
}
3.在Service中实现.aidl 接口
实际实现的接口是在 gen中自动生成的 IaidlData.java的抽象内部类 Stub。
创建好.aidl文件后,刷新项目,在gen包对应的包下会出现与aidl文件相同的Java文件
AIDL工具生成的Java文件中:
public static abstract class Stub extends android.os.Binder implements com.example.processtest.aidl.IStockService //静态抽象内部类
private static class Proxy implements com.example.processtest.aidl.IStockService //AIDL服务代理类
public double getResult(double a, double b) throws android.os.RemoteException //AIDL公布出的接口,就是我们定义的接口方法。
AIDL只是一个契约,我们需要一个服务来提供服务。
提供服务的类ProcessService
public class ProcessService extends Service {
private class IStockServiceImp extends IStockService.Stub{
@Override
public double getResult(double a, double b) throws RemoteException {
// TODO 自动生成的方法存根
return a+b;
}
@Override
public Person getPerson() throws RemoteException {
// TODO 自动生成的方法存根
Person person=new Person();
person.setAge("20");
person.setName("zhangsan");
return person;
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO 自动生成的方法存根
return new IStockServiceImp();
}
@Override
public boolean onUnbind(Intent intent) {
// TODO 自动生成的方法存根
//关闭服务所在的进程
android.os.Process.killProcess(android.os.Process.myPid());
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO 自动生成的方法存根
Log.d("xxx",
android.os.Process.myPid() + ";"
+ Tools.getCurProcessName(getApplicationContext()));
Log.d("xxS", MyApplication.name);
return super.onStartCommand(intent, flags, startId);
}
}
4.进程间的通信
public class MainActivity extends Activity {
private IStockService service2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("xxM", android.os.Process.myPid() + "");
Intent intent = new Intent(getApplicationContext(),
ProcessService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
Log.d("xxM", MyApplication.name);
}
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO 自动生成的方法存根
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO 自动生成的方法存根
service2 = IStockService.Stub.asInterface(service);
try {
Log.d("xx", service2.getResult(5, 9) + "");
Log.d("xxp", service2.getPerson().getAge() + ";"
+ service2.getPerson().getName());
} catch (RemoteException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
};
public boolean onKeyDown(int keyCode, android.view.KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
finish();
// 退出程序时我们一般只调用finish()函数杀死当前Activity,Application退到幕后,由系统自动维护。
// 再次启动程序时就不会执行Application.onCreate(),而是直接执行Activity.onCreate()。
//杀掉进程的方法
android.os.Process.killProcess(android.os.Process.myPid());
return true;
}
return false;
};
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
};
}