为何要使用AIDL
什么是AIDL?
AIDL (Android Interface Definition Language) is similar to other IDLs you might have worked with. It allows you to define the programming interface that both the client and service agree upon in order to communicate with each other using interprocess communication (IPC).
根据上述官方文档的说明,AIDL即为android的接口定义语言,跟其它的接口定义语言是类似的。它能够定义约定好的规范的客户端和服务端之间的编程接口,使得进程间能够互相通信。简单来说就是Android上用来实现IPC的一种方式。何时选择要使用AIDL?
Andriod平台上实现IPC的方式有多种,例如:
非实时性的以通知方式实现简单进程间通信的Intent,Broadcast;
实时性的Binder/Messenger方式都可以实现IPCNote: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.
上述为Android对于AIDL使用的官方提示,即仅当你需要让来自不同应用的多个客户端访问你的service,实现与服务的通信;并且你想要在service内处理多线程。如不是基于这两点需求,建议考虑使用Binder或者Messenger来实现你的进程通信需求。Android系统使用AIDL的实例简介
在android平台提供的framework层提供了各种系统服务,最常见的是wifi,bluetooth,sensor等各种设备的管理和使用。常见使用流程为:
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.cancelAll();
而systemService都是在android系统启动过程中启动的系统服务进程,用户启动应用获取对应的服务管理类,如NotificationManager从而能够调用对应服务提供的功能接口;然而NotificationManager仅仅只是一个管理类,真正实现这些功能的在前面提到的systemService当中。NotificationManager等管理类就是通过AIDL的方式实现与系统服务接口调用。
可参考博文:http://www.2cto.com/kf/201501/370478.html
AIDL的使用简介
既然知晓了AIDL用来在不同进程/应用间通信使用,使用AIDL的最通常也是有Clien和Service。AIDL用来约束规范client与service之间的调用规则,即用于描述二者之间的通信接口。
官方示例:http://developer.android.com/guide/components/aidl.html
博主简要学习示例:
上图为整个示例的包结构,AidlTest仅包含aidl文件,定义了通信接口,项目属性设置为Library,然后客户端和服务端项目,单独拿出aidl文件作为单一的项目Library可以方便得保持client和serverice拥有一致的接口定义文件(当然你也可以在服务端和客户端下分别添加一个aidl文件,不过需要保持包名等的一致性)
- 定义通信接口
AIDL接口定义的语法跟java基本一致,不过这里需要注意直接支持的数据类型仅仅只是基础数据类型以及List/String等,AIDL需要使用额外的数据需要自己加入import;这里示例定义一个很简单的IPerson接口,包含一个greet函数:
package com.example.aidl;
interface IPerson {
String greet(String someone);
}
build之后会自动编译生成对应的IPerson.java在gen目录,IPerson.java内包含一个静态Stub类,以及固有的静态函数asInterface函数:
- 服务端实现
public class AIDL_Server extends Service{
private IPerson.Stub stub = new IPerson.Stub() {
@Override
public String greet(String someone) throws RemoteException {
// TODO Auto-generated method stub
return "Hello, I am " + someone;
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d("joker", "onBind");
return stub;
}
}
- 客户端实现
public class MainActivity extends Activity {
private IPerson mIPerson ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
Log.d("joker", "onServiceDisconnected#########");
mIPerson = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
Log.d("joker", "onServiceConnected");
mIPerson = IPerson.Stub.asInterface(service);
}
};
Button bindButton = (Button) findViewById(R.id.bindservice);
bindButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
bindService(new Intent("android.intent.action.AIDL_Server"), connection, Context.BIND_AUTO_CREATE);
}
});
Button button = (Button) findViewById(R.id.test);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
if( mIPerson == null ) {
Log.d("joker", " Service not connected now maybe. ");
return;
}
String retv = mIPerson.greet("JokerLee");
Log.d("joker", " Call the service greet func : " + retv );
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
从输出结果可以看出客户端和服务的分处于不同的进程,客户端成功调用了service的函数。