Android中使用AIDL技术约束进程通信规则(类似于接口的定义语言)
示例:通过AIDL访问远程服务(remote service)实现通过学生学号查找姓名
1.创建不带Activity的AndroidApplication
2.src目录下创建package并在里面添加文件StudentQuery.aidl
按照接口的方式编写,并去掉访问描述符(public,private等)
package com.example.aidl;
//AIDL 描述规则
interface StudentQuery {
String queryStudent (int number);
}
这个时候在gen文件夹下会生成一大堆代码,主要是StudentQuery接口
3.创建学生查询服务(com.example.remote.service.StudentQueryService.java)继承于Service,
并在AndroidManifest.xml文件中添加服务的隐式意图:
重写onBinder方法,在onBinder方法中,我们要返回IBinder接口对象,这样访问者才可以使用Service类提供的服务,因此,我们声明并创建binder对象:
private IBinder binder = new StudentQueryBinder();
4.此时StudentQueryBinder类不存在,
我们创建它(com.example.remote.service.StudentQueryBinder.java)并且要具备跨应用通信的功能,这个时候就需要继承刚刚自动生成的com.example.aidl.StudentQuery.Stub类,并实现IBinder接口,点击生成未实现的方法(queryStudent),事实上通过查看Stub的源码会发现:
public static abstract class Stub extends android.os.Binder implements com.example.aidl.StudentQuery
Stub在继承Binder同时实现StudentQuery接口
代码:public class StudentQueryBinder extends Stub implements IBinder{
@Override
public String queryStudent(int number) throws RemoteException {
return null;
}
}
在queryStudent方法中实现自己的查询服务(本例中简单起见不访问数据库)
至此完成远程服务代码编写。
这里的需求是当click button的时候完成查询,并将结果显示出来。
1.首先不能忘记的是在src下创建并编写同样的aidl文件,这样在客户端的gen目录下也会生成同样的java文件。
2.为MainActivity绑定服务。
使用bindService方法,我们看到它需要三个参数:
第一个是Intent对象,我们创建并设定隐式意图:
Intent service = new Intent("com.example.student.query");
第三个是一个标志表明绑定中的操作,这里我们使用:
public static final int BIND_AUTO_CREATE = 0x0001;
第二个参数就要好好讲讲,它是实现ServiceConnection的类的对象
所以,我们首先创建内部类StudentConnection并实现ServiceConnection接口
编写未实现的方法:
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
studentQuery=StudentQuery.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
studentQuery=null;
}
这个时候我们获取服务返回的IBinder的对象,此处由于是远程通信,需要使用语句StudentQuery.Stub.asInterface(service);来进行转换(本地服务就不需要)
那么现在我们就可以通过queryStudent接口对象来使用服务了。
3.我们希望通过button来访问服务,这样为button添加一个onClick属性并指定方法:queryStudent
在MainActivity中编写这个方法
public void queryStudent(View v){
intstudentID=Integer.valueOf(editTextStudentID.getText().toString());
try{
textViewResult.setText(studentQuery.queryStudent(studentID));
}catch (RemoteException e) {
e.printStackTrace();
}
}
我们看到通过studentQuery对象来调用queryStudent方法来实现服务的访问。
com.example.remoteserviceclient.MainActivity.java
public class MainActivity extends Activity {
private EditText editTextStudentID;
private TextView textViewResult;
private StudentQuery studentQuery;
private StudentConnection conn = new StudentConnection();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextStudentID = (EditText)this.findViewById(R.id.studentID);
textViewResult=(TextView)this.findViewById(R.id.textViewResult);
Intent service = new Intent("com.example.student.query");
bindService(service, conn, BIND_AUTO_CREATE);
}
public void queryStudent(View v){
int studentID=Integer.valueOf(editTextStudentID.getText().toString());
try {
textViewResult.setText(studentQuery.queryStudent(studentID));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private final class StudentConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
studentQuery=StudentQuery.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
studentQuery=null;
}
}
}
com.example,remote.service.StudentQueryBinder.java
public class StudentQueryBinder extends Stub implements IBinder{
private String[] names = { "张笑", "杨景", "衡通", "阎树信" ,"何宇同"};
private String query(int id) {
if (id < 254 && id > 248)
return names[253 - id];
return "查询结果不在范围";
}
@Override
public String queryStudent(int number) throws RemoteException {
return query(number);
}
}
public class StudentQueryService extends Service {
private IBinder binder=new StudentQueryBinder();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}