源码下载:点击打开链接
我们可以使用AIDL来实现跨进程的方法调用,理解AIDL我们需要理解Binder的概念,如果我们对Binder有了一定的了解,在Binder基础上我们可以更加容易地理解AIDL。
名词解析:IPC(Inter-process Communication )跨进程通信。
AIDL(Android Interface Definition Language)Android接口定义语言。
Android进程间通信方式有多种,今天讲解一下AIDL的使用方法。
AIDL(Android Interface Definition Language)是Android进程间通讯独特的通讯方式,通过绑定Service来实现。
下面以Demo的形式开始今天的讲解,Demo演示通过在客户端(程序A中的Activity)读取服务端(程序B中的Service)的数据,这里的数据是一个对象--继承了Parcelable的People类。
要在进程间通信传递复杂的对象需要以下操作:
- 子类实现Parcelable接口,意味着要实现writeToParcel()和readFromParcel(),writeToParcel()方法将对象写入到包裹(parcel)中,而readFromParcel()方法从包裹中读取对象。注意,写入的顺序必须与读取的顺序相同。
- 向该类添加一个名为CREATOR的static final 属性,该属性需要实现android.os.Parcelable.Creatot<T>接口。
- 为Parcelable提供一个构造函数,该函数知道如何从Parcelable创建对象。
- 在与包含复杂类型的的.java文件匹配的.aidl文件中定义Parcelable类,AIDL编译器在编译AIDL文件时将查找此文件,且要与对应的.java文件放在同一位置下。
- 项目中每个Parcelable都需要一个.aidl文件。
1子类People实现Parcelable
package com.test.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class People implements Parcelable {
public String name;
public int age;
public int height;
public String ID;
public String address;
public String tel;
public String gender;// 性别
public static final Parcelable.Creator<People> CREATOR = new Creator<People>() {
@Override
public People[] newArray(int size) {
// TODO Auto-generated method stub
return new People[size];
}
@Override
public People createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new People(source);
}
};
public People() {
}
public People(Parcel source) {
// TODO Auto-generated constructor stub
readFromParcel(source);
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) { // TODO Auto-generated
// method stub
dest.writeString(name);
dest.writeInt(age);
dest.writeInt(height);
dest.writeString(ID);
dest.writeString(address);
dest.writeString(gender);
}
@Override
public void readFromParcel(Parcel parcel) {
name = parcel.readString();
age = parcel.readInt();
height = parcel.readInt();
ID = parcel.readString();
address = parcel.readString();
tel = parcel.readString();
gender = parcel.readString();
}
}
People.aidl文件示例:
package com.test.aidl;parcelable People;
定义一个ServiceTest类继承Service:
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return new sserviceTest();
}
public class sserviceTest extends AAAA.Stub{
@Override
public People getPeople(String ID) throws RemoteException {
// TODO Auto-generated method stub
People people = new People();
people.name = "高芳";
people.age = 22;
people.address = "山东.东营";
people.gender ="女";
people.height = 161;
people.tel = "未知";
people.ID = ID;
return people;
}
}
编写.aidl文件:
package com.test.aidl;
import com.test.aidl.People;
interface AAAA{
People getPeople(String ID);
}
AndroidMainfest.xml配置
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.service"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service android:name=".ServiceTest">
<intent-filter>
<action android:name="com.inent.action.AAAA"/>
</intent-filter>
</service>
</application>
</manifest>
注意:客户端要调用服务端,把定义的接口文件(.aidl)拷过来,并且包名要跟服务端一样。
客户端:
bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
bindService(new Intent("com.inent.action.AAAA"), serviceConnection, Service.BIND_AUTO_CREATE);
People people = null;
try {
people = mAaaa.getPeople("100");
mTextView.setText("姓名:" + people.name + "\n" + "性别:" + people.gender + "\n" + "年龄:" + people.age
+"\n" + "地址:" + people.address + "\n" + "" );
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
运行时报错,上面红色的那一行报:02-27 14:59:42.699: E/AndroidRuntime(32440): java.lang.NullPointerException
mAaaa是空指针,开始以为绑定没有成功,查看了一下没问题,问题出在,绑定服务时需要异步获取对象,这里开启一个线程获取对象就ok了
bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
bindService(new Intent("com.inent.action.AAAA"), serviceConnection, Service.BIND_AUTO_CREATE);
mHandler.post(runnable);
}
});
public Runnable runnable = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
mHandler.obtainMessage(100).sendToTarget();
}
};
public Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
People people = null;
people = getPeople();
mTextView.setText("姓名:" + people.name + "\n" + "性别:" + people.gender + "\n" + "年龄:" + people.age
+"\n" + "地址:" + people.address + "\n" + "" );
}
};