1简介
AIDL:Android Interface Definition Language,即Android接口定义语言, 是IPC(interprocess communication)进程间通信方式的一种。
2使用
本篇目的是本地通过aidl调用远程service服务,计算传入的两个数值的和并返回的例子,初步掌握AIDL的使用。 闲话少说,先上效果图
2.1 AIDL接口的创建
在java目录下创建aidl文件夹
在aidl文件夹下创建aidl文件 AIDL文件代码实现// ILiujianAidl.aidl
package com.liujian.aidl;
interface ILiujianAidl {
//计算两个数的和
int add(int num1 ,int num2);
}
完成代码后一定要同步一下,Android Studio会自动为我们生成我们最终使用的ILiujianAidl文件。
2.2 远程服务的实现
本例通过设置service的清单文件process属性,使它和客户端的Activity不在同一个进程中,构成多进程通信的场景。
<service
android:name=".IRemoteService"
android:process=":remote"/>
服务端代码实现
public class IRemoteService extends Service {
private final String TAG = "IRemoteService";
/**
* 当客户端绑定该服务时会执行
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
private IBinder iBinder = new ILiujianAidl.Stub() {
@Override
public int add(int num1, int num2) throws RemoteException {
Log.i(TAG,"收到了远程的请求,输入的参数是"+num1+"和"+num2);
return num1 + num2;
}
};
}
2.3客户端的实现
首先要进行绑定服务
/**
* 绑定服务
*/
private void bindService(){
//获取到服务端
Intent intent = new Intent();
//新版本必须显式Intent绑定服务
intent.setComponent(new ComponentName("com.liujian.aidl","com.liujian.aidl.IRemoteService"));
bindService(intent,conn, Context.BIND_AUTO_CREATE);
}
然后获取输入数据
最后调用服务并显示结果
/**
* 调用服务计算结果并显示
*/
private void calculateToShow(int num1,int num2){
try {
//调用远程服务
int res = iLiujianAidl.add(num1,num2);
etRes.setText(res+"");
} catch (RemoteException e) {
e.printStackTrace();
etRes.setText("出错了");
}
}
客户端完整代码
package com.liujian.aidl;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity implements View.OnClickListener{
private EditText etNum1,etNum2,etRes;
private Button btCalculate;
ILiujianAidl iLiujianAidl;
ServiceConnection conn = new ServiceConnection() {
//绑定上服务的时候执行
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//拿到了远程的服务
iLiujianAidl = ILiujianAidl.Stub.asInterface(service);
}
//当服务断开时执行
@Override
public void onServiceDisconnected(ComponentName name) {
//回收
iLiujianAidl = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
bindService();
}
private void initView() {
etNum1 = findViewById(R.id.etNum1);
etNum2 = findViewById(R.id.etNum2);
etRes = findViewById(R.id.etRes);
btCalculate = findViewById(R.id.btCalculate);
btCalculate.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int num1 = Integer.valueOf(etNum1.getText().toString());
int num2= Integer.valueOf(etNum2.getText().toString());
calculateToShow(num1,num2);
}
/**
* 调用服务计算结果并显示
*/
private void calculateToShow(int num1,int num2){
try {
//调用远程服务
int res = iLiujianAidl.add(num1,num2);
etRes.setText(res+"");
} catch (RemoteException e) {
e.printStackTrace();
etRes.setText("出错了");
}
}
/**
* 绑定服务
*/
private void bindService(){
//获取到服务端
Intent intent = new Intent();
//新版本必须显式Intent绑定服务
intent.setComponent(new ComponentName("com.liujian.aidl","com.liujian.aidl.IRemoteService"));
bindService(intent,conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
3其他
3.1AIDL支持的数据类型
-
基本数据类型(int、long、char、boolean、double等)
-
String和CharSequence
-
List:只支持ArrayList,里面每个元素都必须能够被AIDL支持
-
Map:只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value
-
Parcelable:所有实现了Parcelable接口的对象
-
AIDL:所有的AIDL接口本身也可以在AIDL文件中使用
3.2 注意事项
- Parcelable对象和AIDL接口对象必须要显示import进来不管他们是否和当前的AIDL文件处于同一个包内
- 如果AIDL文件中用到了自定义的Parcelable对象,那么必须新建一个和他同名的AIDL文件,并在其中声明它为Parcelable类型
- AIDL中除了基本数据类型,其他类型的参数都必须标上方向:in(输入型参数)、out(输出型参数)、inout(输入输出型参数)
- AIDL接口中只支持方法,不支持声明静态常量