Android--AIDL使用

AIDL介绍

我们通常比较熟悉Android应用程序中进行跨进程访问的组件BroadcastReceiver和ContentProvider,另外一个Android应用程序组件Service也可以,这种可以跨进程访问的服务称为AIDL服务。

AIDL (Android Interface Definition Language)是 Android 提供的一种机制,允许通过跨进程的接口实现不同应用或进程之间的通信。

AIDL 的基本原理

在 Android 中,每个应用运行在自己的独立进程中。当需要跨进程进行通信时,应用间的对象无法直接传递和共享,必须通过 AIDL 接口进行通信。AIDL 会自动生成接口代码来处理复杂的数据类型和方法调用,从而使两个进程可以在不直接共享内存的情况下进行数据交换。

AIDL 使用类似于 Java 接口的语法,并定义一个接口来描述客户端和服务端之间的交互方法。Android 系统通过这一接口来生成代理类和实际实现类,从而实现跨进程调用。

AIDL 的基本工作流程
  1. 定义 AIDL 接口:在服务端应用中,定义一个 AIDL 文件,描述客户端和服务端之间的通信接口。
  2. 生成 Java 接口:使用 AIDL 文件,Android 编译器会自动生成对应的 Java 接口代码。该代码会包含一个接口类(Stub 类)和一个客户端代理类(Proxy 类)。
  3. 实现接口:服务端实现生成的接口方法,客户端通过代理类调用这些方法。
  4. 绑定服务:客户端通过 bindService() 将服务绑定到自己的进程,从而可以通过 AIDL 接口调用服务端的功能。

AIDL使用

通常一个apk就是一个进程,要实现进程间通信需要两个进程,一个作为服务端,一个作为客户端,服务端来定义AIDL接口,写接口实现,客户端可以调用服务端的AIDL接口实现功能。

注意:实现AIDL需要系统权限,准备工作需要在两个进程中都添加系统权限和系统签名。

这里创建一个Project工程,其中的app包名设置为com.example.aidlserver,作为AIDL的服务端,然后新建一个module作为AIDL的客户端,包名设置为com.example.aidlclient

AIDL服务端

1. 定义AIDL服务接口

先在com.example.aidlserver中创建AIDL接口,选中包名右键新建AIDL,接口名为IAidlServer。

create.png
serverAidl.png

在IAidlServer.aidl中增加add()和minus()两个功能接口。

<app/main/aidl/com.example.aidlserver/IAidlServer.aidl>

interface IAidlServer {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    int add(int num1, int num2);
    int minus(int num1, int num2);
}

定义好AIDL接口后先编译一遍,编译之后Android会自动生成AIDL的服务接口,其中实现了stub、proxy的class,以及TRANSACTION的code,用来通信处理。

sever实现.png

2. 实现AIDL服务接口

在com.example.aidlserver中创建Service服务类,实现AIDL中的功能接口。

<app/main/java/com.example.aidlserver/AidlServer.java>

public class AidlServer  extends Service {

    private static final String TAG = "=== AidlServer ===";

    // 服务实体
    private final IAidlServer.Stub mStub = new IAidlServer.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
            Log.d(TAG, "basicTypes ");
        }

        @Override
        public int add(int num1, int num2) throws RemoteException {
            int sum = num1 + num2;
            Log.d(TAG, "add sum = " + sum);
            return sum;
        }

        @Override
        public int minus(int num1, int num2) throws RemoteException {
            int differ = num1 - num2;
            Log.d(TAG, "minus differ = " + differ);
            return differ;
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate ");
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onStart ");
        return mStub;
    }
}

3. 静态注册Service

在AndroidManifest.xml中静态注册AIDL的实现类,将Service对外暴露,这样客户端才能访问。

<app/main/AndroidManifest.xml>

        <service android:name=".AidlServer"
            android:enabled="true"
            android:exported="true">
            <!-- enable:ture设置可用   exported:ture对外暴露 -->
            <intent-filter>
                <action android:name="com.example.aidlserver.aidlserver"/>
            </intent-filter>
        </service>
AIDL客户端

1. 复制服务端的AIDL服务接口

把服务端的AIDL以及包目录完整的拷贝到客户端的mian目录下,让Client和Server的服务对象对等。

clientAidl.png

AIDL接口复制到客户端之后编辑aidlclient模块,在客户端的build中生成服务接口。

client.png

2. 在客户端绑定服务使用接口

首先在客户端的MainActivity页面中添加两个按钮,分别用来触发实现add和minus功能。

然后在MainActivity.java中调用AIDL接口实现功能。

(1)绑定AIDL服务。
(2)调用接口。
(3)解绑AIDL服务。

<aidl/main/java/com.example.aidlserver/MainActivity.java>

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "=== AidlClient ===";

    private IAidlServer aidlServer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // 绑定 AidlService
        Intent intent = new Intent();
        intent.setAction("com.example.aidlserver.aidlserver");
        intent.setPackage("com.example.aidlserver"); // server's package name
        boolean isBound = bindService(intent, connection, BIND_AUTO_CREATE);
        Log.d(TAG, "绑定服务 bindService result: " + isBound);

        initView();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 解绑 AidlService
        unbindService(connection);
        Log.d(TAG, "解绑服务 unbindService finished !");
    }

    private void initView(){

        // add
        findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "add onClick : " + (aidlServer == null));

                if (aidlServer != null) {
                    try {
                        int sum = aidlServer.add(12, 34);
                        Log.d(TAG, "sum = " + sum);
                        Toast.makeText(MainActivity.this, String.valueOf(sum), Toast.LENGTH_SHORT).show();
                    } catch (RemoteException e) {
                        e.printStackTrace();
                        Log.e(TAG, "AidlServer.add error : " + e);
                    }
                }
            }
        });

        // minus
        findViewById(R.id.minus).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "differ onClick : " + (aidlServer == null));

                if (aidlServer != null) {
                    try {
                        int differ = aidlServer.minus(34, 12);
                        Log.d(TAG, "differ = " + differ);
                        Toast.makeText(MainActivity.this, String.valueOf(differ), Toast.LENGTH_SHORT).show();
                    } catch (RemoteException e) {
                        e.printStackTrace();
                        Log.e(TAG, "aidlService.minus error : " + e);
                    }
                }
            }
        });
    }

    private final ServiceConnection connection = new ServiceConnection() {
        // 绑定服务成功
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            // 接受到了远程的服务
            Log.d(TAG, "onServiceConnected!");
            aidlServer = IAidlServer.Stub.asInterface(service);
        }

        // 解绑服务
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d(TAG, "onServiceDisconnected!");
            // 回收资源
            aidlServer = null;
        }
    };
}

先运行服务端,再运行客户端,点击客户端的按钮就可以实现AIDL的接口功能了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容