AIDL在Android开发中用于进程间的通讯,举个例子,你有个程序A中用“张三”这个用户名正在登录,当你打开另一个程序B,想让“张三”这个用户自动登录,那你就需要获取程序A中“张三”用户名和密码。怎么做呢?这便用到了AIDL技术。
下面我们通过一个实例来实现上述应用场景,假设程序A我命名为AIDLServer,作为服务端;程序B我命名为AIDLClient,作为客户端。我们先来编写服务端:
第一步建立aidl文件,基础数据类型都可以;List、Map也可以,但其里面的内容也必须是java基础数据类型。
IAIDLServer.aidl:
package com.demo.aidlserver;
import com.demo.aidlserver.User;
interface IAIDLServer{
String sayHello();
User getUser();
}
如使用Object类型,需要该对象implement Parcelable接口,并且需要导入该接口包名+类名,且建立对象名.aidl文件声明该对象。
User.java:
package com.demo.aidlserver;
import android.os.Parcel;
import android.os.Parcelable;
public class User implements Parcelable {
private String userName;
private String userPwd;
private int age;
public User(){}
public User(Parcel parcel){
userName = parcel.readString();
userPwd = parcel.readString();
age = parcel.readInt();
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(userName);
dest.writeString(userPwd);
dest.writeInt(age);
}
public static final Parcelable.Creator<User> CREATOR = new Creator<User>(){
@Override
public User createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new User(source);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
User.aidl:
parcelable User;
做完上述操作后保存,会发现gen目录下会自动生成IAIDLServer.java
,不必修改里面的内容!
第二步实现aidl接口,实际实现的接口是在 gen中自动生成的 IAIDLServer.java的抽象内部类Stub。建立AIDLServerService.java,继承Service,上面所说的IAIDLServer.java
内包含一个抽象类stub,其继承了android.os.Binder,所以需要在onBind()方法中返回实现该类的对象。
package com.demo.aidlserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class AIDLServerService extends Service{
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private IAIDLServer.Stub mBinder = new IAIDLServer.Stub() {
@Override
public String sayHello() throws RemoteException {
return "Hello World!!!";
}
@Override
public User getUser() throws RemoteException {
User user = new User();
user.setUserName("zhangsan");
user.setUserPwd("123456");
user.setAge(25);
return user;
}
};
}
第三步AndroidManifest.xml中配置对应service。
<service android:name="com.demo.aidlserver.AIDLServerService"
android:process=":remote">
<intent-filter>
<action android:name="com.demo.aidlserver.IAIDLServer"></action>
</intent-filter>
</service>
至此,Server端编写完毕,目录结构如下图:
接下来我们来看下客户端的编写流程:
第一步是把服务器程序里关于要共享数据的接口的代码连同包一起拷过来,如下图:
第二步是当客户端调用bindService()方法就将绑定到指定Service
Intent service = new Intent("com.demo.aidlserver.IAIDLServer");
bindService(service, mConnection, BIND_AUTO_CREATE);
actoin的属性的采用aidl文件的类名+包名(与服务一致),之前需要在服务中设置相同的action属性,否则找不到服务。
第三步是客户端的OnServiceConnected()方法里调用IAIDLServerService.Stub.asInterface()将得到服务器端OnBind方法里IBinder类实例。
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mServer = IAIDLServer.Stub.asInterface(service);
try {
Toast.makeText(MainActivity.this, mServer.sayHello(), Toast.LENGTH_LONG).show();
String mText = "";
mText += "姓名:" + mServer.getUser().getUserName() + "\n";
mText += "密码:" + mServer.getUser().getUserPwd() + "\n";
mText += "年龄:" + mServer.getUser().getAge();
mTv.setText(mText);
} catch (RemoteException e) {
e.printStackTrace();
}
}
至此,全部逻辑完毕,客户端文档目录结构图如下:
运行Server,然后在运行Client,点击click按钮即可获得Server中的User对象并展示。以上例子仅起到抛砖引玉的作用,具体深层次的研究还需各位对源码进行研究。
源码下载地址