1、AIDL简介
- AIDL(Android Interface Definition Language)名为Android接口定义语言,从定义上不难看出其作用,它是用来定义接口的,而它定义的接口正是进程间的通信接口。
- 我们在学习Service的时候用到一个接口IBinder,当我们在Activity中需要了解到Service在后台执行任务的进度时,我们就会利用到IBinder来完成进度的监控,但是若是在进程之间(不同的应用之间)通信的话,就需要用到AIDL了。
- AIDL用于在不同进程之间数据共享和相互操作。
2、远程服务的开启
下面的代码操作要用到上一篇博客Service基础中创建的名为Service
的项目。
2.1、远程启动服务
1、新建一个名为AIDLDemo的项目,布局文件代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="operate"
android:text="远程启动服务" />
<Button
android:id="@+id/stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="operate"
android:text="远程停止服务" />
<Button
android:id="@+id/bind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="operate"
android:text="远程绑定服务" />
<Button
android:id="@+id/unbind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="operate"
android:text="远程解绑服务" />
</LinearLayout>
2.同时打开上一篇博客创建的项目Service
,打开AndroidManifest.xml
文件,修改器service标签
内容,此处加了意图过滤器,然后为action指定一个别名,这里命名为com.chaixingsi.myservice
,为远程操作MyService做准备。
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.chaixingsi.myservice" />
</intent-filter>
</service>
3.继续编写AIDLDemo
项目的代码,打开MainActivity
,代码如下:
public void operate(View view) {
switch (view.getId()) {
case R.id.start:
Intent intent = new Intent();
//这里设置为Service项目中MyService的name属性名
intent.setAction("com.chaixingsi.myservice");
intent.setPackage("com.demo.service");
startService(intent);
break;
}
}
4.首先运行上一个应用Service
,然后在运行当前应用AIDLDemo
,在当前项目的Logcat窗口中选择上一个项目,并添加过滤词,看能否远程启动服务,单击当前项目远程启动服务
按钮,日志打印结果如下,符合预期。
5.同样地,我们为远程停止服务按钮添加事件,代码如下:
case R.id.stop:
Intent intent2 = new Intent();
intent2.setAction("com.chaixingsi.myservice");
intent2.setPackage("com.demo.service");
stopService(intent2);
break;
2.2、远程绑定服务
1.继续完成MainActivity的绑定和解绑的代码,如下:
case R.id.bind:
Intent intent3 = new Intent();
intent3.setAction("com.chaixingsi.myservice");
intent3.setPackage("com.demo.service");
bindService(intent3, serviceConnection, BIND_AUTO_CREATE);
break;
case R.id.unbind:
unbindService(serviceConnection);
break;
2.依次点击远程绑定服务→远程解绑服务,打印日志如下所示:
3、远程服务的通信
我们在远程操纵服务的时候,无法看到任务处理的进度,这个时候就需要借助AIDL来实现。
3.1、创建AIDL文件
1.打开Service
项目,在MainActivity
所在包内创建AIDL文件,默认名为IMyAidlInterface
,新建完成之后发现项目结构中多了一个aidl文件夹,如下图所示:
2.在IMyAidlInterface.aidl
中添加以下方法,用于显示进度,这里并不实现它(接口中不用实现方法)。
void showProgress();
3.为了生成对应的Java文件,单击菜单栏【Build】→【Rebuild Project】,待项目Build成功,将浏览模式切换到【Project】,如下图所示即为aidl文件对应生成的Java文件。
3.2、实现AIDL
修改MyService
中onBind
方法,创建IMyAidlInterface.Stub
方法,这里仅打印一条日志。
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "服务绑定了");
return new IMyAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
//先不用管这个方法
}
@Override
public void showProgress() throws RemoteException {
Log.d(TAG, "showProgress: " + i + "%");
}
};
}
3.3、实现远程监控服务进度
1.打开MainActivity
,修改ServiceConnection
中的onServiceConnected
方法(注释或删掉之前的代码)。
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//MyService.MyBinder myBinder = (MyService.MyBinder) service;
//Log.d(TAG, "onServiceConnected,此时操作进度为: " + myBinder.getProcess() + "%");
IMyAidlInterface iMyAidlInterface=IMyAidlInterface.Stub.asInterface(service);
try {
iMyAidlInterface.showProgress();
} catch (RemoteException e) {
e.printStackTrace();
}
}
2.到目前为止,我们这样修改代码,Service项目的运行效果和之前的是一样的(实现方法有所改变而已
)。
3.然后在AIDLDemo
项目的main
文件夹下新建一个名为aidl
文件夹,创建一个包(这里的包名要和Service
项目的aidl文件所在的包的包名一致,这里为com.demo.service
),然后将Service项目下的aidl文件拷贝到此处。同样地,我们Build一下项目,生成对应Java文件,以便使用。
4.修改AIDLDemo
项目的MainActivity下的ServiceConnection对象的方法,代码如下:
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyAidlInterface iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
iMyAidlInterface.showProgress();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
5.同样地,先运行Service项目,在运行AIDLDemo项目,然后依次
点击远程启动服务→远程绑定服务→远程解绑服务→远程绑定服务→远程解绑服务→远程绑定服务→远程解绑服务→远程停止服务
,打印日志如下所示:
从上面看,AIDL本质的的作用就是用于生成可用的Java类(接口),然后通过这个Java类来完成我们的需求。