5、AIDL-Android强化课程笔记

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

修改MyServiceonBind方法,创建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类来完成我们的需求。

猜你喜欢

转载自blog.csdn.net/chaixingsi/article/details/81217478
今日推荐