AIDL的基本使用

222 阅读3分钟

1简介

AIDL:Android Interface Definition Language,即Android接口定义语言, 是IPC(interprocess communication)进程间通信方式的一种。

2使用

本篇目的是本地通过aidl调用远程service服务,计算传入的两个数值的和并返回的例子,初步掌握AIDL的使用。 闲话少说,先上效果图

2.1 AIDL接口的创建

在java目录下创建aidl文件夹

在aidl文件夹下创建aidl文件
AIDL文件代码实现

// ILiujianAidl.aidl
package com.liujian.aidl;

interface ILiujianAidl {

    //计算两个数的和
    int add(int num1 ,int num2);
}

完成代码后一定要同步一下,Android Studio会自动为我们生成我们最终使用的ILiujianAidl文件。

2.2 远程服务的实现

本例通过设置service的清单文件process属性,使它和客户端的Activity不在同一个进程中,构成多进程通信的场景。

<service
        android:name=".IRemoteService"
        android:process=":remote"/>

服务端代码实现

public class IRemoteService extends Service {

    private final  String TAG = "IRemoteService";

    /**
     * 当客户端绑定该服务时会执行
     * @param intent
     * @return
     */
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

    private IBinder iBinder = new ILiujianAidl.Stub() {
        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.i(TAG,"收到了远程的请求,输入的参数是"+num1+"和"+num2);
            return num1 + num2;
        }
    };
}

2.3客户端的实现

首先要进行绑定服务

 /**
     * 绑定服务
     */
    private void bindService(){
        //获取到服务端
        Intent intent = new Intent();
        //新版本必须显式Intent绑定服务
        intent.setComponent(new ComponentName("com.liujian.aidl","com.liujian.aidl.IRemoteService"));

        bindService(intent,conn, Context.BIND_AUTO_CREATE);
    }

然后获取输入数据

最后调用服务并显示结果

/**
     * 调用服务计算结果并显示
     */
    private void calculateToShow(int num1,int num2){
        
        try {
            //调用远程服务
            int res = iLiujianAidl.add(num1,num2);
            etRes.setText(res+"");
        } catch (RemoteException e) {
            e.printStackTrace();
            etRes.setText("出错了");
        }
    }

客户端完整代码

package com.liujian.aidl;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements View.OnClickListener{

    private EditText etNum1,etNum2,etRes;
    private Button btCalculate;
    ILiujianAidl iLiujianAidl;
    ServiceConnection conn = new ServiceConnection() {
        //绑定上服务的时候执行
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //拿到了远程的服务
            iLiujianAidl = ILiujianAidl.Stub.asInterface(service);
        }

        //当服务断开时执行
        @Override
        public void onServiceDisconnected(ComponentName name) {
            //回收
            iLiujianAidl = null;
        }
    };

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

        initView();
        bindService();
    }

    private void initView() {
        etNum1 = findViewById(R.id.etNum1);
        etNum2 = findViewById(R.id.etNum2);
        etRes = findViewById(R.id.etRes);
        btCalculate = findViewById(R.id.btCalculate);
        btCalculate.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int num1 = Integer.valueOf(etNum1.getText().toString());
        int num2= Integer.valueOf(etNum2.getText().toString());
        calculateToShow(num1,num2);
    }

    /**
     * 调用服务计算结果并显示
     */
    private void calculateToShow(int num1,int num2){

        try {
            //调用远程服务
            int res = iLiujianAidl.add(num1,num2);
            etRes.setText(res+"");
        } catch (RemoteException e) {
            e.printStackTrace();
            etRes.setText("出错了");
        }
    }




    /**
     * 绑定服务
     */
    private void bindService(){
        //获取到服务端
        Intent intent = new Intent();
        //新版本必须显式Intent绑定服务
        intent.setComponent(new ComponentName("com.liujian.aidl","com.liujian.aidl.IRemoteService"));

        bindService(intent,conn, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
    }
}

3其他

3.1AIDL支持的数据类型

  • 基本数据类型(int、long、char、boolean、double等)

  • String和CharSequence

  • List:只支持ArrayList,里面每个元素都必须能够被AIDL支持

  • Map:只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value

  • Parcelable:所有实现了Parcelable接口的对象

  • AIDL:所有的AIDL接口本身也可以在AIDL文件中使用

3.2 注意事项

  • Parcelable对象和AIDL接口对象必须要显示import进来不管他们是否和当前的AIDL文件处于同一个包内
  • 如果AIDL文件中用到了自定义的Parcelable对象,那么必须新建一个和他同名的AIDL文件,并在其中声明它为Parcelable类型
  • AIDL中除了基本数据类型,其他类型的参数都必须标上方向:in(输入型参数)、out(输出型参数)、inout(输入输出型参数)
  • AIDL接口中只支持方法,不支持声明静态常量

3.3选择合适的IPC方式