AIDL(Android Interface Definition Language):Android接口定义语言。用来实现Android进程间通信(IPC),通俗点说就是一个APP可以被另一个APP调用,该APP向另一个APP提供数据。
官方文档(感兴趣的可以看看)
使用步骤(这里使用的是Android Studio)
第一步 在服务端定义一个AIDL接口
在一个.aidl文件中使用java编程语言语法定义你的AIDL接口,然后在提供service的应用中和任何绑定到这个service的应用中的源代码中(在src目录下)保存它
1、创建一个Service文件RemoteService。
在AndroidManifest配置文件中配置该Service的action标签:
2、创建指定Service对应的.aidl文件
AIDL文件要和Service的包名一致。选中要提供的服务类,右键 -> New -> AIDL -> AIDL File文件,如图所示在main文件夹下的aidl文件夹下创建了一个名为RemoteInterface.aidl的文件,Service和该AIDL文件的包名也是一样的,
3、在该.aid文件下添加AIDL的方法。
默认情况下,AIDL 支持下列数据类型:
- Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
- String
- CharSequence
- List
List 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 可选择将 List 用作“通用”类(例如,List)。另一端实际接收的具体类始终是 ArrayList,但生成的方法使用的是 List 接口。 - Map
Map 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 不支持通用 Map(如 Map<String,Integer> 形式的 Map)。 另一端实际接收的具体类始终是 HashMap,但生成的方法使用的是 Map 接口。
定义服务接口时,请注意:
方法可带零个或多个参数,返回值或空值。
所有非原语参数都需要指示数据走向的方向标记。可以是 in、out 或 inout(见以下示例)。
原语默认为 in,不能是其他方向。
注意:您应该将方向限定为真正需要的方向,因为编组参数的开销极大。
.aidl 文件中包括的所有代码注释都包含在生成的 IBinder 接口中(import 和 package 语句之前的注释除外)
只支持方法;您不能公开 AIDL 中的静态字段。
5、重新编译一下项目,如果成功编译那么会生成一个名为RemoteInterface.java的接口文件,并且声明了.aidl中所有的方法,该文件中还有一个名为Stub的抽象静态内部类,继承RemoteInterface接口继承Binder类。
6、向客户端公开该接口
要为您的服务公开该接口,请扩展第一步中的 Service 并实现 onBind(),并返回一个Stub类实例。
public class RemoteService extends Service {
public RemoteService() {
}
@Override
public IBinder onBind(Intent intent) {
// Return the interface
return mBinder;
}
private final RemoteInterface.Stub mBinder = new RemoteInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void setString(String str) throws RemoteException {
}
@Override
public String getString() throws RemoteException {
return "成功调用远程服务";
}
};
}
现在,当客户端(如 Activity)调用 bindService() 以连接此服务时,客户端的 onServiceConnected() 回调方法会接收该服务 onBind() 方法返回的 mBinder 实例。
第二步 在客户端调用接口
1、在客户端的aidl文件夹下面要有和服务端相同目录结构的.aidl文件。一般我们直接从服务端拷贝过来即可,然后Rebuild Project,结束后会生成和服务端一模一样的接口文件本例中为RemoteInterface.java。
2、调用服务端暴露的方法
public class MainActivity extends AppCompatActivity {
private Button btCallAIDL;
private RemoteInterface aidlService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btCallAIDL = (Button) findViewById(R.id.bt_call_aidl);
// 点击按钮绑定服务端的服务
btCallAIDL.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.dtcdkl.aidlservice.remote"); // 参数为服务端的Service的action的name参数的值
intent.setPackage("com.dtcdkl.aidlservice"); // 参数为服务端的包名
bindService(intent, new MyConnection(), BIND_AUTO_CREATE);// 绑定Service
}
});
}
private class MyConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
aidlService = RemoteInterface.Stub.asInterface(service);// 获得服务端的RemoteInterface的对象。
try {
String str = aidlService.getString();// 调用服务端暴露的方法
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}