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

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

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

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

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

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

java 复制代码
		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() 来检查服务器是否抛出了异常。
相关推荐
安东尼肉店2 小时前
Android compose屏幕适配终极解决方案
android
2501_916007472 小时前
HTTPS 抓包乱码怎么办?原因剖析、排查步骤与实战工具对策(HTTPS 抓包乱码、gzipbrotli、TLS 解密、iOS 抓包)
android·ios·小程序·https·uni-app·iphone·webview
feiyangqingyun3 小时前
基于Qt和FFmpeg的安卓监控模拟器/手机摄像头模拟成onvif和28181设备
android·qt·ffmpeg
用户2018792831677 小时前
ANR之RenderThread不可中断睡眠state=D
android
煤球王子7 小时前
简单学:Android14中的Bluetooth—PBAP下载
android
小趴菜82277 小时前
安卓接入Max广告源
android
齊家治國平天下7 小时前
Android 14 系统 ANR (Application Not Responding) 深度分析与解决指南
android·anr
ZHANG13HAO7 小时前
Android 13.0 Framework 实现应用通知使用权默认开启的技术指南
android
【ql君】qlexcel7 小时前
Android 安卓RIL介绍
android·安卓·ril
写点啥呢7 小时前
android12解决非CarProperty接口深色模式设置后开机无法保持
android·车机·aosp·深色模式·座舱