Android多进程开发 - AIDL 最简单的实现、传递数据大小限制
Android多进程开发 - AIDL 最简单的实现、传递数据大小限制
·
一、AIDL 最简单的实现
1、Server
(1)Setting
- 在模块级
build.gradle文件中添加如下内容,配置开启 AIDL 功能
android {
buildFeatures {
aidl true
}
}
(2)AIDL
-
在
src/main目录下创建 aidl 目录 -
在
src/main/aidl目录下创建com/my/common目录 -
在
src/main/aidl/com/my/common目录下创建并编辑IMyAidlInterface.aidl文件
package com.my.common;
interface IMyAidlInterface {
int add(int a, int b);
String greet(String name);
}
- 编译项目,生成
IMyAidlInterface.java文件,生成的文件位于build/generated/aidl_source_output_dir/debug/out/com/my/common目录下
(3)Service
- ServerService.java
public class ServerService extends Service {
private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
@Override
public int add(int a, int b) throws RemoteException {
return a + b;
}
@Override
public String greet(String name) throws RemoteException {
return "Hello, " + name;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
(4)AndroidManifest
- AndroidManifest.xml
<service
android:name=".service.ServerService"
android:exported="true">
<intent-filter>
<action android:name="com.my.server.ServerService" />
</intent-filter>
</service>
(5)Activity
- activity_main.xml
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Server"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}
2、Client
(1)Setting
- 在模块级
build.gradle文件中添加如下内容,配置开启 AIDL 功能
android {
buildFeatures {
aidl true
}
}
(2)AIDL
-
在
src/main目录下创建 aidl 目录 -
在
src/main/aidl目录下创建com/my/common目录 -
将 Server 中的
IMyAidlInterface.aidl文件复制到src/main/aidl/com/my/common目录下
package com.my.common;
interface IMyAidlInterface {
int add(int a, int b);
String greet(String name);
}
- 编译项目,生成
IMyAidlInterface.java文件,生成的文件位于build/generated/aidl_source_output_dir/debug/out/com/my/common目录下
(3)Activity
- activity_main.xml
<?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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Client"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_connect_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="连接服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_text" />
<Button
android:id="@+id/btn_test_method_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试 add 方法"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_connect_service" />
<Button
android:id="@+id/btn_test_method_greet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试 greet 方法"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_test_method_add" />
</androidx.constraintlayout.widget.ConstraintLayout>
- MainActivity.java
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
private IMyAidlInterface myAidlInterface;
private boolean isBound = false;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "服务连接成功");
myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
isBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "服务连接断开");
myAidlInterface = null;
isBound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
findViewById(R.id.btn_connect_service).setOnClickListener(v -> {
Intent intent = new Intent();
intent.setAction("com.my.server.ServerService");
intent.setPackage("com.my.server");
bindService(intent, connection, BIND_AUTO_CREATE);
});
findViewById(R.id.btn_test_method_add).setOnClickListener(v -> {
try {
int result = myAidlInterface.add(5, 3);
Log.i(TAG, "add result: " + result);
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "add method error: " + e.getMessage());
}
});
findViewById(R.id.btn_test_method_greet).setOnClickListener(v -> {
try {
String result = myAidlInterface.greet("Client");
Log.i(TAG, "greet result: " + result);
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "greet method error: " + e.getMessage());
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isBound) {
unbindService(connection);
}
}
}
3、Test
- 先启动 Server 应用,再启动 Client 应用
- 点击 Client 应用中的【连接服务】按钮,输出如下结果
# Client
服务连接成功
- 点击 Client 应用中的【测试 add 方法】按钮,输出如下结果
# Client
add result: 8
- 点击 Client 应用中的【测试 greet 方法】按钮,输出如下结果
# Client
greet result: Hello, Client
二、传递数据大小限制
1、Server 向 Client 传递
(1)AIDL
interface IMyAidlInterface {
byte[] getData();
}
(2)Server
@Override
public byte[] getData() throws RemoteException {
// 传递 1MB - 9KB 数据
byte[] data = new byte[1024 * 1024 - 9 * 1024];
for (int i = 0; i < data.length; i++) {
data[i] = (byte) i;
}
return data;
}
(3)Client
try {
byte[] data = myAidlInterface.getData();
Log.i(TAG, "getData result length: " + data.length);
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "getData method error: " + e.getMessage());
}
(4)Test
- 传递 1MB - 9KB 数据,输出如下结果
# Client
getData result length: 1039360
- 传递 1MB - 8KB 数据,输出如下结果
# Client
getData method error: Transaction failed on small parcel; remote process probably died
- 传递 1MB - 7KB 数据,输出如下结果
# Client
getData method error: Transaction failed on small parcel; remote process probably died
2、Client 向 Server 传递
(1)AIDL
interface IMyAidlInterface {
void sendData(in byte[] data);
}
(2)Server
@Override
public void sendData(byte[] data) throws RemoteException {
Log.i(TAG, "sendData input length: " + data.length);
}
(3)Client
try {
// 传递 1MB - 9KB 数据
byte[] data = new byte[1024 * 1024 - 9 * 1024];
for (int i = 0; i < data.length; i++) {
data[i] = (byte) (i + 100);
}
myAidlInterface.sendData(data);
Log.i(TAG, "sendData method success");
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "sendData method error: " + e.getMessage());
}
(4)Test
- 传递 1MB - 9KB 数据,输出如下结果
# Server
sendData input length: 1039360
# Client
sendData method success
- 传递 1MB - 8KB 数据,输出如下结果
# Client
sendData method error: data parcel size 1040464 bytes
- 传递 1MB - 7KB 数据,输出如下结果
# Client
sendData method error: data parcel size 1041488 bytes
更多推荐
所有评论(0)