一、介绍
AIDL
(Android Interface Definition Language)是安卓接口定义语言,是一种实现跨进程通信的方式。我们都知道,安卓系统还上各个进程都在自己的独立空间中运行并且互不干扰,因此要实现进程间直接进行数据共享的话很难做到。但是借助AIDL
,我们能够轻易打破进程边界,实现进程间的通信。
二、使用场景
虽然
AIDL
作用很大,但并不是所有情况下都是最好的跨进程通信方案,那么什么场景下才适合使用呢?对此,官方给出的解释是:“只有当你允许来自不同应用程序的客户端远程访问你的服务并且在你的服务中处理多线程的情况下才使用AIDL
;如果不需要跨应用程序实现并发进程间通信的话,那么你应该使用Binder
接口;如果只是进程间通信,但不许处理多线程,那么使用Messenger
。”
三、使用步骤
- 创建
.aidl
文件- 实现
.aidl
文件中的接口- 将接口暴露给客户端
四、使用示例
1.创建
.aidl
文件并定义接口
在Android Studio中项目的Project
视图下,鼠标右键app/src
目录,选择New -> AIDL -> AIDL File
,将Interface name
命名为IMyAidlInterface
,然后点击Finish
确认。Synchronize项目后会在src/main/packge
目录下生成IMyInterface.aidl
文件,文件内容如下:
//Filename: IMyInterface.aidl
interface IMyInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
//自定义接口
String getInfor(String s);
}
- 实现
.aidl
文件中的接口
鼠标右键app/src
目录,选择New -> Service -> Service
,将Service
命名为MyService
,在该Service
中实现IMyInterface.aidl
接口。文件内容如下:
//Filename: MyService.java
public class MyService extends Service {
public final String TAG = this.getClass().getName();
public MyService() {
}
private IBinder binder = new IMyInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public String getInfor(String s) throws RemoteException {
Log.i(TAG,"s = " + s);
return "我是"+TAG+"返回的自负串";
}
};
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG,"onCreate");
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return binder;
}
}
通过以上方式生成的Service
会自动在AndroidManifest.xml
中注册服务,我们需要让该Service
在一个不同的进程中运行,所以需要再添加android:process="com.example.remote"
属性
//Filename: AndroidManifest.xml
<service
android:name=".MyService"
android:enabled="true"
android:process="com.example.remote"
android:exported="true">
</service>
- 将接口暴露给客户端
接着在客户端调用AIDL接口,在MainActivity.java
文件中添加如下代码:
//Filename: MainActivity.java
public class MainActivity extends AppCompatActivity {
public final String TAG = this.getClass().getName();
private IMyInterface myInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
startAndBindService();
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myInterface = IMyInterface.Stub.asInterface(service);
Log.i(TAG,"链接Service成功");
try {
String s = myInterface.getInfor("我是"+TAG+"传来的字符串");
}catch (RemoteException e){
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG,"链接Service失败");
}
};
private void startAndBindService(){
Intent service = new Intent(MainActivity.this, MyService.class);
bindService(service,serviceConnection, Context.BIND_AUTO_CREATE);
}
}
五、运行结果
2019-07-12 10:03:12.626 26045-26045/? I/com.example.aidldemo.MyService: onCreate
2019-07-12 10:03:12.629 26029-26029/? I/com.example.aidldemo.MainActivity: 链接Service成功
2019-07-12 10:03:12.630 26045-26057/? I/com.example.aidldemo.MyService: s = 我是com.example.aidldemo.MainActivity传来的字符串