当前位置: 首页 > article >正文

【Android】直接使用binder的transact来代替aidl接口

aidl提供了binder调用的封装,有的时候,比如:

1. 懒得使用aidl生成的接口文件(确实是懒,Android studio中aidl生成接口文件很方便)

2. 服务端的提供者只公开了部分接口出来,只给了调用编号和参数(这个设计就很奇怪,其实可以提供fake的aidl文件,暴露部分方法即可)

3. 想看看更直观的binder通信的调用

可以使用transcat调用,以下是直观的一个例子

		try {
//获取服务,可以使用反射来实现
	    	IBinder aProxyBinder = (IBinder)getSystemService("lam");//atest
	    	if (aProxyBinder != null){
	    		Log.d(TAG, "lam not null");
	    	}	    		
	    	else {
	    			Log.d(TAG, "lam is null");
			}
	    	
	    	
	    	 Parcel dataParcel = Parcel.obtain(); 
	    	 Parcel resultParcel = Parcel.obtain();
	  dataParcel.writeInterfaceToken(DESCRIPTOR);
	   //发起请求	 
	     aProxyBinder.transact(3, dataParcel, resultParcel, 0);

在 Android 中,直接使用 Binder 的 transact 方法来调用 Binder 接口是一种底层的方法,通常用于自定义的 IPC(进程间通信)场景。这种方式绕过了 AIDL 自动生成的代码,允许你手动进行跨进程调用。下面将介绍如何直接使用 transact 方法来调用 Binder 接口。

1. 理解 transact 方法

transact 方法是 IBinder 类中的一个关键方法,它用于执行跨进程请求。其原型如下:

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException;
  • code: 请求码,标识要调用的具体方法。
  • data: 输入参数,封装在 Parcel 对象中。
  • reply: 输出结果,同样封装在 Parcel 对象中。
  • flags: 标志位,控制事务的行为(如 FLAG_ONEWAY 表示异步调用)。

2. 定义和实现 Binder 接口

首先,你需要定义一个接口,并提供相应的服务端实现。这个过程可以通过 AIDL 来完成,但为了演示如何直接使用 transact,我们将不使用 AIDL 自动生成的 stub 类。

假设我们有一个简单的服务接口 IMyService,它包含一个名为 doSomething 的方法,该方法接受一个字符串作为输入,并返回一个字符串作为输出。

2.1 服务端实现
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

public class MyService extends Binder {
    private static final int TRANSACTION_DO_SOMETHING = IBinder.FIRST_CALL_TRANSACTION + 0;

    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        if (code == TRANSACTION_DO_SOMETHING) {
            data.enforceInterface("com.example.IMyService");

            String input = data.readString();
            String output = doSomething(input);

            reply.writeInterfaceToken("com.example.IMyService");
            reply.writeString(output);
            return true;
        }
        return super.onTransact(code, data, reply, flags);
    }

    public String doSomething(String input) {
        // 实现你的业务逻辑
        return "Hello, " + input;
    }
}

在这个例子中,我们重写了 onTransact 方法,并根据传入的 code 来处理不同的请求。对于 TRANSACTION_DO_SOMETHING 请求,我们从 Parcel 中读取输入数据,调用 doSomething 方法处理数据,然后将结果写回到 reply 中。

2.2 客户端调用

接下来,我们需要编写客户端代码来使用 transact 方法调用 doSomething 方法。

import android.os.Binder;
import android.os.Parcel;
import android.os.RemoteException;

public class MyClient {
    private IBinder binder;

    public MyClient(IBinder binder) {
        this.binder = binder;
    }

    public String callDoSomething(String input) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();

        try {
            data.writeInterfaceToken("com.example.IMyService");
            data.writeString(input);

            // 调用 transact 方法
            boolean result = binder.transact(MyService.TRANSACTION_DO_SOMETHING, data, reply, 0);

            if (result) {
                // 读取回复数据
                reply.readException(); // 检查是否有异常抛出
                return reply.readString();
            } else {
                throw new RemoteException("Transaction failed.");
            }
        } finally {
            data.recycle();
            reply.recycle();
        }
    }
}

在这个例子中,我们创建了两个 Parcel 对象:datareply。我们使用 writeInterfaceToken 方法为 data 写入接口令牌,然后写入方法参数。接着,我们调用 transact 方法发送请求,并通过 reply 读取响应数据。最后,不要忘记回收 Parcel 对象以释放资源。

3. 注意事项

  • 错误处理:在调用 transact 方法时,务必检查返回值并处理可能的异常。例如,可以使用 reply.readException() 来检查服务器是否抛出了异常。


http://www.kler.cn/a/501792.html

相关文章:

  • 《自动驾驶与机器人中的SLAM技术》ch8:基于 IESKF 的紧耦合 LIO 系统
  • 自动连接校园网wifi脚本实践(自动网页认证)
  • Linux创建server服务器实现多方信息收发
  • 对话新晋 Apache SeaTunnel Committer:张圣航的开源之路与技术洞察
  • 信息系统项目管理-采购管理-采购清单示例
  • 1、docker概念和基本使用命令
  • nacos从1.x升级到2.4.3问题记录
  • 【C++指南】模板 深度解析
  • 如何使用队列规则(Qdisc)发送数据包
  • Git | git reset命令详解
  • python安装完成后可以进行的后续步骤和注意事项
  • leetcode 2270. 分割数组的方案数 中等
  • 【WPS】【WORDEXCEL】【VB】实现微软WORD自动更正的效果
  • windows wsl ubuntu22 远程桌面连接
  • QT跨平台应用程序开发框架(1)—— 环境搭建
  • Redis集群的键分布机制
  • Y3编辑器地图教程:ORPG教程、防守图教程
  • 扩散模型学习
  • Arthas监控方法内部调用路径,并输出方法路径上的每个节点上耗时
  • 计算机网络之---端口与套接字
  • 机器学习之K-mean算法理解及实现
  • Java中的反射机制及其应用场景
  • Day05-后端Web基础——TomcatServletHTTP协议SpringBootWeb入门
  • YOLOv8从菜鸟到精通(二):YOLOv8数据标注以及模型训练
  • CentOS7下Hadoop集群分布式安装详细图文教程
  • [Qt]常用控件介绍-按钮类控件