AIDl:android interface define language 安卓接口定义语言,这是一种新的语言,它可以被编译器自动编译为java语言,具体方法为在应用项目java文件夹中:
“New –> File –> AIDL”
然后定义自己需要用到的接口方法,点击:
“Build -> Make Project”
然后在Project视图下的“\app\build\generated\source\aidl\debug\项目文件目录”中可以看到相应的java文件
为了解决进程间通讯,定义了两个应用程序之间的通讯规则。
他和接口非常的相似,我们可以先定义接口,再把接口修改为aidl.java –> .aidl (老版Eclipse可以这么做,现在我们用Android Studio可以参考上面的方式创建aidl)
aidl语言有自己的语法:
1 它可以识别java里面的基本数据类型
2 它无法识别访问修饰符 public private
3 它无法识别domain
如果要让aidl识别domain (实体类)
1 class Student implements Parcelable
2 写一个Student.aidl文件
package cn.itcast.domain;
parcelable Student;
aidl 自动生成.java文件后,我们使用什么?
Stub
asInterface(IBinder) IStudent
底层其实走的是代理机制。
aidl 就是一个合同 一式两份,写完aidl之后,把aidl所有的内容带包一起复制到客户端
在介绍可以实现远程服务的aidl之前,我们先讲一下本地服务的实现方式。本地服务就是在同一个应用中,使用绑定服务实现的一种方式。我们要了解一下为什么要绑定服务,其实绑定服务可以帮助我们调用服务里面的方法,下面我们举一个案例加以说明:
需求是通过Activity中的查询按钮,调用服务的queryNameById(int id)方法进行查询并返回到Activity当中,那么接下来就是代码的完善了~
1、订阅接口
/**
* 接口
* 接口的抽取:有什么样的行为,就抽取什么样的方法
* @author apple
*
*/
public interface IStudentListener {
//根据学号查询学生的姓名
public String queryNameById(int id);
}
2、服务
public class MyService extends Service {
private String[] names = new String[]{"张学友","刘德华","黎明","郭富城"};
//增强版IBinder(真实的对象)
private MyBinder ibinder = new MyBinder();
@Override
public IBinder onBind(Intent intent) {
return ibinder;
}
//创建一个增强版的IBinder类
private class MyBinder extends Binder implements IStudentListener{
@Override
public String queryNameById(int id) {
//id只能是1 到4
if(id <= 0 || id > names.length){
return "苍姐姐";
}else{
return names[id-1];
}
}
}
}
3、客户端
public class MainActivity extends Activity {
private EditText et_id;
private Button bt_query;
private TextView tv_name;
private MyServiceConnection conn;
private IStudentListener iStudentListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_id = (EditText) findViewById(R.id.et_id);
bt_query = (Button) findViewById(R.id.bt_query);
tv_name = (TextView) findViewById(R.id.tv_name);
//绑定服务
conn = new MyServiceConnection();
bindService(new Intent(this,MyService.class), conn, BIND_AUTO_CREATE);
}
private class MyServiceConnection implements ServiceConnection{
//绑定成功
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
bt_query.setEnabled(true);
//把IBinder对象转化成接口对象
iStudentListener = (IStudentListener) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
public void query(View v){
//绑定服务(为什么服务的绑定需要时间)
String idStr = et_id.getText().toString().trim();
if(TextUtils.isEmpty(idStr)){
Toast.makeText(this, "姐姐 学号不能为空", 0).show();
}else{
int id = Integer.parseInt(idStr);
//调用接口对象的方法(就是调用真实对象的方法)
String name = iStudentListener.queryNameById(id);
tv_name.setText(name);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
1、创建aidl文件
首先还是先要创建aidl文件,文件名为:IStudentListener.aidl,具体可以参考这篇博客android studio使用aidl
2、服务器
/**
* 远程的服务(在其他应用程序里面的服务)
* @author apple
*
*/
public class MyService extends Service {
private String[] names = new String[]{"张学友","刘德华","黎明","郭富城"};
private MyBinder ibinder = new MyBinder();
@Override
public IBinder onBind(Intent intent) {
return ibinder;
}
//增强版的IBinder
private class MyBinder extends IStudentListener.Stub{
@Override
public String queryNameById(int id) throws RemoteException {
//id只能是1 到4
if(id <= 0 || id > names.length){
return "苍姐姐";
}else{
return names[id-1];
}
}
}
}
AndroidManifest.xml我们需要添加这样的配置:
其中,intent-filter的作用是便于隐式调用该Service.
<service android:name=".MyService">
<intent-filter>
<action android:name="cn.itcast.action.studentquerysystem.server" />
service>
3、客户端(可以创建一个moudle、或者另外创建一个项目)
从服务器端把aidl文件带包一起复制过来,这里有坑,需要做的是我们复制过来,而不是自己手动新建aidl文件夹和文件,不然会报个莫名其妙的error……
public class MainActivity extends Activity {
private EditText et_id;
private TextView tv_name;
private MyServiceConnection conn;
private IStudentListener iStudentListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_id = (EditText) findViewById(R.id.et_id);
tv_name = (TextView) findViewById(R.id.tv_name);
//绑定服务
Intent service = new Intent();
service.setAction("cn.itcast.action.studentquerysystem.server");
conn = new MyServiceConnection();
bindService(service, conn, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
private class MyServiceConnection implements ServiceConnection{
//绑定的服务是一个远程的服务,传递过来的对象是个代理对象,而代理对象不能直接使用
//需要使用Stub里面的一个方法:asInterface()把代理对象转化成真实对象再使用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//把代理对象转化成真实对象
iStudentListener = MyService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
public void query(View v){
String idStr = et_id.getText().toString().trim();
if(TextUtils.isEmpty(idStr)){
Toast.makeText(this, "姐姐 学号不能为空", 0).show();
}else{
int id = Integer.parseInt(idStr);
//调用接口对象的方法(就是调用真实对象的方法)
try {
String name = iStudentListener.queryNameById(id);
tv_name.setText(name);
} catch (RemoteException e) {
e.printStackTrace();
Toast.makeText(this, "服务器端出现了错误", 0).show();
}
}
}
}
这样,简单的跨应用的远程服务用AIDL就这样解决了,如果你还要在aidl文件中传入引用类型对象,就需要这个对象继承Parcelable接口,还需要在该aidl文件夹新建一个同名的aidl文件,例如我们需要一个Book对象,我们就要先创建一个Book.aidl文件。好啦先这样吧~