AIDL入门学习一

0、相关资料

视频:AIDL-小白成长记

文章:Android AIDL使用详解

1、概述

官方文档:Android 接口定义语言 (AIDL)

以下摘抄自官方文档:

Android 接口定义语言 (AIDL) 与您可能使用过的其他接口语言 (IDL) 类似。您可以利用它定义客户端与服务均认可的编程接口,以便二者使用进程间通信 (IPC) 进行相互通信。在 Android 中,一个进程通常无法访问另一个进程的内存。因此,为进行通信,进程需将其对象分解成可供操作系统理解的原语,并将其编组为可供您操作的对象。编写执行该编组操作的代码较为繁琐,因此 Android 会使用 AIDL 为您处理此问题。

注意:只有在需要不同应用的客户端通过 IPC 方式访问服务,并且希望在服务中进行多线程处理时,您才有必要使用 AIDL。如果您无需跨不同应用执行并发 IPC,则应通过实现 Binder 来创建接口;或者,如果您想执行 IPC,但需要处理多线程,请使用 Messenger 来实现接口。无论如何,在实现 AIDL 之前,请您务必理解绑定服务

在开始设计 AIDL 接口之前,请注意,AIDL 接口的调用是直接函数调用。您无需对发生调用的线程做任何假设。实际情况的差异取决于调用是来自本地进程中的线程,还是远程进程中的线程。具体而言:

  • 来自本地进程的调用在发起调用的同一线程内执行。如果该线程是您的主界面线程,则其将继续在 AIDL 接口中执行。如果该线程是其他线程,则其便是在服务中执行代码的线程。因此,只有在本地线程访问服务时,您才能完全控制哪些线程在服务中执行(但若出现此情况,您根本无需使用 AIDL,而应通过实现 Binder 类来创建接口)。
  • 远程进程的调用分派自线程池,且平台会在您自己的进程内部维护该线程池。您必须为来自未知线程,且多次调用同时发生的传入调用做好准备。换言之,AIDL 接口的实现必须基于完全的线程安全。如果调用来自同一远程对象上的某个线程,则该调用将依次抵达接收器端。
  • oneway 关键字用于修改远程调用的行为。使用此关键字后,远程调用不会屏蔽,而只是发送事务数据并立即返回。最终接收该数据时,接口的实现会将其视为来自 Binder 线程池的常规调用(普通的远程调用)。如果 oneway 用于本地调用,则不会有任何影响,且调用仍为同步调用。

2、代码实战

AIDL案例:
    定义AIDL文件
    实现服务端
    实现客户端

思路图:

 2.1、服务端

2.1.1、创建 .aidl 文件

// IImoocAidl.aidl
package com.test.server;

// Declare any non-default types here with import statements

interface IImoocAidl {

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

}

然后make project,会生成IImoocAidl.java文件

 项目目录:

2.1.2、实现接口

public class IRemoteService extends Service {

    private static final String TAG = "IRemoteService";

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

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

}

2.1.3、向客户端公开接口

public class IRemoteService extends Service {

    private static final String TAG = "IRemoteService";

    /**
     * 当客户端绑定到该服务的时候,会执行此方法
     * @param intent
     * @return
     */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

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

}

2.1.4、配置文件注册Service并启动Service

配置文件注册:

 <service
            android:name=".IRemoteService"
            android:exported="true" />

启动Service:

public class MainActivity extends AppCompatActivity {

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

        Intent intent = new Intent(this, IRemoteService.class);
        startService(intent);
    }

}

2.2、客户端

在同项目中新建一个名为client的module 

2.2.1、创建客户端界面

ClientActivity

public class ClientActivity extends AppCompatActivity {

    EditText etNum1, etNum2;
    TextView tvRes;
    Button btnAdd;

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

        etNum1 = findViewById(R.id.et_num1);
        etNum2 = findViewById(R.id.et_num2);
        tvRes = findViewById(R.id.tv_res);
        btnAdd = findViewById(R.id.btn_add);

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });
    }
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ClientActivity">

    <EditText
        android:id="@+id/et_num1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入第一个数字"
        android:textSize="22sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="+"
        android:textSize="100sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_num1" />

    <EditText
        android:id="@+id/et_num2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入第二个数字"
        android:textSize="22sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_add" />

    <TextView
        android:id="@+id/tv_res"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="计算结果"
        android:textSize="40sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_num2" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="计算"
        android:textSize="22sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_res" />

</androidx.constraintlayout.widget.ConstraintLayout>

2.2.2、把服务端的aidl文件拷贝到客户端

 2.2.3、绑定服务并拿取数据

public class ClientActivity extends AppCompatActivity {

    private static final String TAG = "ClientActivity";

    EditText etNum1, etNum2;
    TextView tvRes;
    Button btnAdd;

    IImoocAidl iImoocAidl;

    private ServiceConnection mConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            // 拿到了远程服务
            iImoocAidl = IImoocAidl.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            // 回收资源
            iImoocAidl = null;
        }
    };

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

        etNum1 = findViewById(R.id.et_num1);
        etNum2 = findViewById(R.id.et_num2);
        tvRes = findViewById(R.id.tv_res);
        btnAdd = findViewById(R.id.btn_add);

        bindService();

        btnAdd.setOnClickListener(view -> {
            int num1 = Integer.parseInt(etNum1.getText().toString());
            int num2 = Integer.parseInt(etNum2.getText().toString());

            try {
                // 调用远程服务
                if (null != iImoocAidl) {
                    int res = iImoocAidl.add(num1, num2);
                    tvRes.setText("计算结果为:" + res);
                } else {
                    Log.e(TAG, "iImoocAidl is null!");
                }
            } catch (RemoteException e) {
                e.printStackTrace();
                tvRes.setText("Error!");
            }

        });
    }

    private void bindService() {
        // 获取服务端
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.test.server",
                "com.test.server.IRemoteService"));
        bindService(intent, mConn, BIND_AUTO_CREATE);
    }


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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值