美文网首页面试题
通过AIDL进行IPC进程间通信

通过AIDL进行IPC进程间通信

作者: 付凯强 | 来源:发表于2019-09-20 00:00 被阅读0次

1. AIDL是什么

AIDL即接口定义语言,可以利用它定义客户端与服务均认可的编程接口,以便二者使用进程间通信 (IPC) 进行相互通信。
在 Android 中,一个进程通常无法访问另一个进程的内存。因此,为进行通信,进程需将其对象分解成可供操作系统理解的原语,并将其编组为可供您操作的对象。编写执行该编组操作的代码较为繁琐,因此 Android 会使用 AIDL 为您处理此问题。
在我看来,接口定义语言,相当于一个脚本,可以根据某些规则来生成一些代码,从而实现某种功能。
注意:只有在需要不同应用的客户端通过 IPC 方式访问服务,并且希望在服务中进行多线程处理时,您才有必要使用 AIDL。如果您无需跨不同应用执行并发 IPC,则应通过实现 Binder 来创建接口;或者,如果您想执行 IPC,但需要处理多线程,请使用 Messenger 来实现接口。

2. 支持的基本数据类型

// IMyAidlInterface.aidl
package com.example.testaidl;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * 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);
}

可以支持的数据类型有

  1. 基本数据类型: int、long、char、boolean、float、double。
  2. String、CharSequence
  3. List: 只支持ArrayList,里面每个元素都必须能够被AIDL支持。
  4. Map: 只支持HashMap,里面每个元素都必须被AIDL支持,包括key和value。
  5. Parcelable: 所有实现了Parcelable接口的对象。
  6. AIDL: 所有的AIDL接口本身也可以在AIDL文件中使用。

3. 服务端

提供接口,供其他应用调用的称为服务端。

  • 创建包名com.example.testaidl的Module
  • 创建IAidlServer.aidl
// IAidlServer.aidl
package com.example.aidl_server;
// Declare any non-default types here with import statements
interface IAidlServer {
   int add(int first,int second);
}

创建AIDL文件,然后Make Project,生成IAidlServer接口文件

  • 创建Service
public class IRemoteService extends Service {

    private static final String TAG = "IRemoteService";

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private IBinder mBinder = new IAidlServer.Stub() {
        @Override
        public int add(int first, int second) throws RemoteException {
            Log.d(TAG, "收到远程请求,输入的参数为" + first + "和" + second);
            return first + second;
        }
    };
}

IRemoteService供客户端进行绑定,绑定以后会回调一个Binder对象,这个Binder对象和上一篇文章讲到的Binder在实质上一样,都是Binder对象,只是对象的实例方式不一样。

  • 注册Service
        <service
            android:name=".IRemoteService"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.aidl"></action>
            </intent-filter>
        </service>

注册Service的同时,约定bindService的action。

4. 客户端

调用其他应用接口的被称为客户端。

  • 创建包名为com.example.testaidl的Moudle
  • 把服务端中aidl完整的文件夹拷贝到位于main下面的相同位置
  • 绑定Service
Intent intent = new Intent();
intent.setPackage("com.example.aidl_server");
intent.setAction("com.example.aidl");
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);

指定包名和action

  • 回调获取服务端Binder对象
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mAidlServer = IAidlServer.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mAidlServer = null;
        }
    };

onServiceConnected是建立连接时的回调,onServiceDisconnected是断开连接时的回调。

  • 调用服务端方法
            try {
                    int first_num = Integer.parseInt(ed_firtst.getText().toString());
                    int second_num = Integer.parseInt(ed_second.getText().toString());
                    int value = mAidlServer.add(first_num, second_num);
                    Log.d(TAG, "经过远程计算,两个Int值相加的结果为" + value);
             } catch (RemoteException e) {
                    e.printStackTrace();
             }
2019-09-19 22:21:49.140 5387-5387/com.example.testaidl D/MainActivity: 经过远程计算,两个Int值相加的结果为9

5. 项目地址

https://pan.baidu.com/s/1Mx5MW8DuzWHOYC5_V5kYAQ

6. 后续

如果大家喜欢这篇文章,欢迎点赞!
如果想看更多 IPC 方面的文章,欢迎关注!

相关文章

网友评论

    本文标题:通过AIDL进行IPC进程间通信

    本文链接:https://www.haomeiwen.com/subject/vigfuctx.html