【Android基础】应用层AIDL接口的实现

本文介绍了应用层定义AIDL接口并使用其通信的简单手法。
通常包括以下步骤
定义AIDL接口文件
首先,通信的服务端和客户端,需要创建一个AIDL文件来定义接口。AIDL文件类似于Java接口文件,但它使用AIDL语法。例如,你可以创建一个名为IAirConditionerService.aidl的文件,并在其中定义你的接口方法。客户端和服务端,需要在同一个包名的文件夹里面创建。
interface IAIRConditionerService {
void setTemperature(int temperature);
int getTemperature();
// 其他方法...
}
编译AIDL文件
在Android Studio中,点击build之后,AIDL文件会自动编译。编译后,会生成一个Java接口文件,位于app/build/generated/source/aidl/debug/目录下(假设你的项目是在debug模式下编译的)。这个生成的Java接口文件包含了与AIDL文件中定义的接口相对应的方法。
实现服务端的Service类
接下来,你需要创建一个Service类来实现AIDL接口。这个Service类将处理来自客户端的请求。在Service类中,你需要实现AIDL接口中定义的所有方法。
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class AirConditionerService extends Service {
private final IAIRConditionerService.Stub binder = new IAIRConditionerService.Stub() {
@Override
public void setTemperature(int temperature) throws RemoteException {
// 实现设置温度的逻辑
}
@Override
public int getTemperature() throws RemoteException {
// 实现获取温度的逻辑
return 0;
}
// 其他方法的实现...
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
然后在AndroidManifest.xml中注册Service:你需要在AndroidManifest.xml文件中注册你的Service,以便系统能够找到并启动它。
客户端调用
在客户端应用中,你可以通过绑定到Service来调用AIDL接口中的方法。首先,你需要创建一个ServiceConnection对象,并在其中实现onServiceConnected和onServiceDisconnected方法。然后,你可以使用bindService方法来绑定到Service。
// 客户端Activity或Service
public class AirConditionerClientActivity extends AppCompatActivity {
private IAIRConditionerService airConditionerService;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
airConditionerService = IAIRConditionerService.Stub.asInterface(service);
try {
int temperature = airConditionerService.getTemperature();
// 处理返回的温度值
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
airConditionerService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_air_conditioner_client);
Intent intent = new Intent(this, AirConditionerService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
}
}
一般手机平台上,两个三方app之间要建立这个连接,客户端需要在AndroidManifest里面加一条权限声明:
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
实际的例子
这是我的第一个Android项目,模仿网易云音乐开发了一个约等于静态界面的app,体验了AIDL接口的跨进程通信。
- 客户端:“网抑云”app
- 服务端:一个扫描sdcard内音乐文件的服务进程
直接先看项目文件:
Server

首先就是aidl文件夹,里面定义了通信的接口声明aidl和需要传输的实体类Music的aidl.
AIDLtest.aidl
package com.example.server;
import com.example.server.Music;
interface AIDLtest {
int add(int num1, int num2);
List<Music> getmusiclist();
List<Music> addmusic();
}
我们扫描到音频文件之后,需要将信息通过Music类包装传过去。
Music.aidl
// Music.aidl
package com.example.server;
parcelable Music;
Mudic.java
package com.example.server;
import android.os.Parcel;
import android.os.Parcelable;
public class Music implements Parcelable {
public String name;
public String singer;
public Music() {
}
protected Music(Parcel in) {
name = in.readString();
singer = in.readString();
}
public static final Creator<Music> CREATOR = new Creator<Music>() {
@Override
public Music createFromParcel(Parcel in) {
return new Music(in);
}
@Override
public Music[] newArray(int size) {
return new Music[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSinger() {
return singer;
}
public void setSinger(String singer) {
this.singer = singer;
}
@Override
public String toString() {
return "Music{" +
"name='" + name + '\'' +
", singer='" + singer + '\'' +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(singer);
}
}
java类需要实现Parcelable接口才可以顺利传输,写法是比较固定的。
Client

客户端建立aidl文件夹时,各个类所属的包名一定要和服务端一致,可以看到图片中aidl文件夹是直接从服务端移植过来的。
需要注意的是,实体类Music,java文件的定义,也需要和服务端的包名一致,这里是单独建了一个包来放置它。
至于后面的调用流程就和上面一节提到的是一致的了。
车载Android上普遍的方式
上面的是手机端比较基础的通信集成方式,在车载Android领域,需要跨进程通信时,往往会采取对客户端最友好的方式来实现。
我们会在服务端的代码仓库里面直接新建一个libary的模组。
或者单独做一个仓库,来放置不同app的对外接口文件。
在这些地方,由服务端,也就是接口提供方的开发工程师,来完成客户端的Service连接逻辑,并把方法包装成aar提供给需求方。
然后客户端需求方的项目去集成这个aar,自己决定什么时机调用。