【Android -- IPC】AIDL 的基本使用

什么是 AIDL

AIDL:Android Interface Definition Language,即 Android 接口定义语言;用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。

AIDL 支持的数据类型

共 4 种:

  1. Java 的基本数据类型
  2. List 和 Map
    • 元素必须是 AIDL 支持的数据类型
    • Server 端具体的类里则必须是 ArrayList 或者 HashMap
  3. 其他 AIDL 生成的接口
  4. 实现 Parcelable 的实体

使用

在多进程通信中,存在两个进程角色(以最简单的为例):服务器端和客户端。

服务器端(Service)

步骤1:新建定义AIDL文件,并声明该服务需要向客户端提供的接口;
image

步骤2:在Service子类中实现AIDL中定义的接口方法,并定义生命周期的方法(onCreat、onBind()、blabla)

// 在新建的AIDL_Service1.aidl里声明需要与Activity进行通信的方法
package scut.carson_ho.demo_service;

interface AIDL_Service1 {
    void AIDL_Service();
}
//AIDL中支持以下的数据类型
//1. 基本数据类型
//2. String 和CharSequence
//3. List 和 Map ,List和Map 对象的元素必须是AIDL支持的数据类型;
//4. AIDL自动生成的接口(需要导入-import)
//5. 实现android.os.Parcelable 接口的类(需要导入-import)

image

public class MyService extends Service {
    
    // 实例化AIDL的Stub类(Binder的子类)
    AIDL_Service1.Stub mBinder = new AIDL_Service1.Stub() {

        //重写接口里定义的方法
        @Override
        public void AIDL_Service() throws RemoteException {
            System.out.println("客户端通过AIDL与远程后台成功通信");
        }
    };

//重写与Service生命周期的相关方法
    @Override
    public void onCreate() {
        super.onCreate();

        System.out.println("执行了onCreat()");

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("执行了onStartCommand()");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("执行了onDestory()");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {

        System.out.println("执行了onBind()");
    //在onBind()返回继承自Binder的Stub类型的Binder,非常重要
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        System.out.println("执行了onUnbind()");
        return super.onUnbind(intent);
    }

}

步骤3:在AndroidMainfest.xml中注册服务 & 声明为远程服务

       <service
            android:name=".MyService"
            android:process=":remote"  //将本地服务设置成远程服务
            android:exported="true"      //设置可被其他进程调用
            >
            //该Service可以响应带有scut.carson_ho.service_server.AIDL_Service1这个action的Intent。
            //此处Intent的action必须写成“服务器端包名.aidl文件名”
            <intent-filter>
                <action android:name="scut.carson_ho.service_server.AIDL_Service1"/>
            </intent-filter>

        </service>

客户端(Client)

步骤1:拷贝服务端的AIDL文件到目录下
复制后的目录

步骤2:使用Stub.asInterface接口获取服务器的Binder,根据需要调用服务提供的接口方法
MainActivity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <Button
        android:layout_centerInParent="true"
        android:id="@+id/bind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="绑定服务"
        />
</RelativeLayout>

步骤3:通过Intent指定服务端的服务名称和所在包,绑定远程Service
MainActivity.java

public class MainActivity extends AppCompatActivity {

        private Button bindService;

        //定义aidl接口变量
        private AIDL_Service1 mAIDL_Service;

        //创建ServiceConnection的匿名类
        private ServiceConnection connection = new ServiceConnection() {

            //重写onServiceConnected()方法和onServiceDisconnected()方法
            //在Activity与Service建立关联和解除关联的时候调用
            @Override
            public void onServiceDisconnected(ComponentName name) {
            }

            //在Activity与Service建立关联时调用
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {

                //使用AIDLService1.Stub.asInterface()方法获取服务器端返回的IBinder对象
                //将IBinder对象传换成了mAIDL_Service接口对象
                mAIDL_Service = AIDL_Service1.Stub.asInterface(service);

                try {

                    //通过该对象调用在MyAIDLService.aidl文件中定义的接口方法,从而实现跨进程通信
                    mAIDL_Service.AIDL_Service();

                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        };


        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            bindService = (Button) findViewById(R.id.bind_service);

            //设置绑定服务的按钮
            bindService.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    
                    //通过Intent指定服务端的服务名称和所在包,与远程Service进行绑定
                    //参数与服务器端的action要一致,即"服务器包名.aidl接口文件名"
                    Intent intent = new Intent("scut.carson_ho.service_server.AIDL_Service1");
                    
                    //Android5.0后无法只通过隐式Intent绑定远程Service
                    //需要通过setPackage()方法指定包名
                    intent.setPackage("scut.carson_ho.service_server");
                    
                    //绑定服务,传入intent和ServiceConnection对象
                    bindService(intent, connection, Context.BIND_AUTO_CREATE);

                }
            });
        }

    }

推荐文献:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin-Dev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值