以下是一个简单的 Android 示例,用于测试 Binder 传输数据限制。该示例包含一个服务(Service
),通过 Binder 机制与客户端(Activity
)进行通信,并逐步增加传输的数据量,以确定触发 TransactionTooLargeException
异常(表示超过 Binder 传输限制)时的数据大小。
1. 创建 AIDL 文件
在 Android Studio 中,右键点击 app/src/main
目录,选择 New
-> AIDL
-> AIDL File
,创建一个名为 IBinderTest.aidl
的文件,内容如下:
aidl
// IBinderTest.aidl
package com.example.binderlimitdemo;
interface IBinderTest {
void sendLargeData(in byte[] data);
}
AIDL(Android Interface Definition Language)用于定义跨进程通信的接口,这里定义了一个方法 sendLargeData
用于接收字节数组数据。
2. 创建服务类
创建一个继承自 Service
的类 BinderTestService
,实现上述 AIDL 定义的接口:
java
package com.example.binderlimitdemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class BinderTestService extends Service {
private static final String TAG = "BinderTestService";
// 继承自AIDL生成的Stub类,实现接口方法
private final IBinderTest.Stub binder = new IBinderTest.Stub() {
@Override
public void sendLargeData(byte[] data) throws RemoteException {
// 这里可以添加实际的业务逻辑,我们测试时只打印数据长度
Log.d(TAG, "Received data length: " + data.length);
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
3. 在 AndroidManifest.xml 中注册服务
在 app/src/main/AndroidManifest.xml
文件中添加服务的注册声明:
注意:BinderTestService要设置独立进程,否则不会触发binder大小限制,试过不设置进程demo干到anr了。
ini
<service
android:name=".BinderTestService"
android:enabled="true"
android:process=":binder_test"
android:exported="true">
</service>
4. 创建测试 Activity
创建一个 MainActivity
用于测试 Binder 传输,逐步增加数据量并尝试发送:
java
package com.example.binderlimitdemo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private IBinderTest binderTest;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
binderTest = IBinderTest.Stub.asInterface(service);
testBinderLimit();
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
binderTest = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startButton = findViewById(R.id.start_button);
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, BinderTestService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
});
}
private void testBinderLimit() {
int size = 1024 * 100; // 初始数据大小设为100KB,可根据需要调整起始值
while (true) {
byte[] data = new byte[size];
try {
binderTest.sendLargeData(data);
Log.d(TAG, "Successfully sent data of size: " + size + " bytes");
size += 1024 * 100; // 每次增加100KB
} catch (RemoteException e) {
if (e instanceof android.os.TransactionTooLargeException) {
Log.e(TAG, "Reached Binder transaction size limit at size: " + size + " bytes", e);
} else {
Log.e(TAG, "RemoteException", e);
}
break;
}
}
unbindService(connection);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (connection != null) {
unbindService(connection);
}
}
}
5. 布局文件(activity_main.xml)
在 res/layout
目录下的 activity_main.xml
文件中,添加一个按钮用于启动测试:
xml
ini
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<Button
android:id="@+id/start_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Binder Limit Test" />
</LinearLayout>
运行该应用,点击按钮后,应用会逐步增加通过 Binder 传输的数据量,直到触发 TransactionTooLargeException
异常,此时日志中会记录下达到 Binder 传输大小限制时的数据量。
测试log如下,该系统上限制是 1024000 bytes左右,系统提示限制1040384 bytes,真实限制在1040288 bytes,比系统提示少 96 bytes 。
text
int size = 1024 * 1015;
Successfully sent data of size: 1039360 bytes
int size = 1024 * 1016;
com.example.myapplication E !!! FAILED BINDER TRANSACTION !!! (parcel size = 1040480)
com.example.myapplication E Reached Binder transaction size limit at size: 1040384 bytes
请注意,以上代码基于 Android 平台,运行时需要 Android 设备或模拟器,并且实际的 Binder 传输大小限制可能因设备和系统版本的不同而有所差异。