一、AIDL 最简单的实现

1、Server
(1)Setting
  • 在模块级 build.gradle 文件中添加如下内容,配置开启 AIDL 功能
android {
    buildFeatures {
        aidl true
    }
}
(2)AIDL
  1. src/main 目录下创建 aidl 目录

  2. src/main/aidl 目录下创建 com/my/common 目录

  3. src/main/aidl/com/my/common 目录下创建并编辑 IMyAidlInterface.aidl 文件

package com.my.common;

interface IMyAidlInterface {
    int add(int a, int b);
    String greet(String name);
}
  1. 编译项目,生成 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
  1. src/main 目录下创建 aidl 目录

  2. src/main/aidl 目录下创建 com/my/common 目录

  3. 将 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);
}
  1. 编译项目,生成 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 应用
  1. 点击 Client 应用中的【连接服务】按钮,输出如下结果
# Client

服务连接成功
  1. 点击 Client 应用中的【测试 add 方法】按钮,输出如下结果
# Client

add result: 8
  1. 点击 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
  1. 传递 1MB - 9KB 数据,输出如下结果
# Client

getData result length: 1039360
  1. 传递 1MB - 8KB 数据,输出如下结果
# Client

getData method error: Transaction failed on small parcel; remote process probably died
  1. 传递 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
  1. 传递 1MB - 9KB 数据,输出如下结果
# Server

sendData input length: 1039360
# Client

sendData method success
  1. 传递 1MB - 8KB 数据,输出如下结果
# Client

sendData method error: data parcel size 1040464 bytes
  1. 传递 1MB - 7KB 数据,输出如下结果
# Client

sendData method error: data parcel size 1041488 bytes
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐