Android中AIDL进程间通信使用详解

一、概述

AIDL 是Android的进程间通信(IPC)比较常用的一种方式,AIDL 是 Android Interface Definition Language 的缩写,即Android接口定义语言。

 

Android中,每一个进程都有自己的Dalvik VM实例,拥有一个独立的内存空间,进程与进程之间是不共享内存的,每个进程都在自己的内存空间内进程数据存储,有时候我们需要两个进程之间进行数据交互,这就产生了进程间通信的需求。

 

AIDL优点

1.进程间通信不止有AIDL,我们还有其他选择,例如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 存在占用的系统资源比较多和存在延迟问题,在频繁的跨进程通信时是无法满足需求的;Messenger 进行跨进程通信时请求队列是同步进行的,无法并发执行,不能进行多进程通信,局限性比加大,这个时候就需要使用 AIDL 了。

 

2.编译器通过*.aidl文件的描述信息生成符合通信协议的Java代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作。

 

二、AIDL的基本使用

 

AIDL的底层是基于Binder实现的,而Binder机制也是一种请求-响应式的通信模型,请求方一般称为Client,响应方称为Server

 

这里我提供一个Demo,Demo中AIDLServiceClient为服务端,AIDLClient为客户端,这里需要AIDLServiceClient对外提供接口,方便AIDLClient在需要向AIDLServiceClient传递数据或者使用AIDLServiceClient的存储数据。

 

首先分别创建AIDLServiceClient(服务端)和AIDLClient(客户端)两个项目,作为服务端和客户端使用。

服务端

在AIDLServiceClient项目中创建AIDL接口。

src\main 目录 右键new一个AIDL文件。

输入自定义AIDL名字,点击OK,即可创建出AIDL接口文件,文件中会默认生出一个basicTypes方法,该方法描述了AIDL中可以使用的基本类型(int, long, boolean, float, double, String)。

自定义自己的方法名,可以删除不需要的basicTypes方法,定义后需要Sync Project。

// IAidlServiceInterface.aidl
package com.fanxb.aidlserviceclient;

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

interface IAidlServiceInterface {
    String getMessages();
}

创建一个实现类,继承刚才创建的AIDL的名称里的Stub类,并实现接口方法。

public class IAidlInterfaceImpl extends IAidlServiceInterface.Stub {
    @Override
    public String getMessages() throws RemoteException {
        return "This is the AIDL ServiceClient message!";
    }
}

创建AIDLService类,并初始化IAidlInterfaceImpl实现类,onBind方法中返回IAidlInterfaceImpl 实现类的实例。

public class AidlService extends Service {

    private IAidlInterfaceImpl mIAidlInterface;

    @Override
    public void onCreate() {
        super.onCreate();
        mIAidlInterface = new IAidlInterfaceImpl();
    }

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

创建ServiceAppliction类,在这里启动AIDLService。

public class ServiceApplication extends Application {
    public static Context sContext;

    @Override
    public void onCreate() {
        super.onCreate();
        sContext = this;
        startService(new Intent(this, AidlService.class));
    }

    public static Context getContext() {
        return sContext;
    }
}

 

在AndroidManifest.xml文件里配置Application 标签 name属性,指向所创建的ServiceAppliction类。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.fanxb.aidlserviceclient">

    <application
        android:name=".ServiceApplication"

在AndroidManifest.xml文件里配置service,其中< intent-filter > 标签中的 action name 自定义,在客户端需要绑定服务端时设置同样的action,指向该服务建立连接。

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

          package="com.fanxb.aidlserviceclient">



    <application

               //

       <service

    android:name="com.fanxb.aidlserviceclient.AidlService"

    android:enabled="true">

       <intent-filter>

        <action android:name="com.fanxb.aidlserviceclient.service"/>

        <category android:name="android.intent.category.DEFAULT"/>

       </intent-filter>

      </service>
    </application>

</manifest>

 

 

客户端

将服务端AIDL文件拷贝到客户端相同包的位置,然后Sync Project。

注意:客户端和服务端AIDL的文件和路径要一致。

 

新建ClientAppliction类,这里演示在这里绑定服务端,简历进程通信。通过隐式意图来绑定service, ServiceConnection可以获取连接回调,有两个方法,onServiceConnected 连接成功,onServiceDisconnected连接失败,我们可以根据实际的需求在不同的方法里处理业务逻辑。

public class ClientAppliction extends Application {

    private static Context sContext;

    private static IAidlServiceInterface sIAidlServiceInterface;

    @Override
    public void onCreate() {
        super.onCreate();
        sContext = this;
        bindService();
    }

    /**
     * bind AIDL Service
     */
    private void bindService() {
        Intent intent = new Intent();
        intent.setAction("com.fanxb.aidlserviceclient.service");
        intent.setPackage("com.fanxb.aidlserviceclient");
        bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
    }

    /**
     * Service Connection callback
     */
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            sIAidlServiceInterface = IAidlServiceInterface.Stub.asInterface(iBinder);
            Log.i("===========>", "Server connected successfully!!!");
            try {
                String message = sIAidlServiceInterface.getMessages();
                Log.i("===========>", "the message:" + message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

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

    public static Context getContext() {
        return sContext;
    }

    public static void setContext(Context context) {
        sContext = context;
    }

    public static IAidlServiceInterface getIAidlServiceInterface() {
        return sIAidlServiceInterface;
    }

    public static void setIAidlServiceInterface(IAidlServiceInterface IAidlServiceInterface) {
        sIAidlServiceInterface = IAidlServiceInterface;
    }
}

 

在onServiceConnected方法中通过IAidlServiceInterface.Stub.asInterface(service)获取IAidlServiceInterface对象,然后在onClick中调用IAidlServiceInterface.getMessage()。

 

三、AIDL的进阶使用

客户端向服务端发送数据

在服务端的AIDL文件里添加void sendMessageToService(String message)方法,记得Sync Project
 

// IAidlServiceInterface.aidl
package com.fanxb.aidlserviceclient;

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

interface IAidlServiceInterface {
    String getMessages();
    void sendMessageToService(String message);
}

在服务端的IAidlInterfaceImpl类里重写sendMessageToService方法,接收客户端消息。

public class IAidlInterfaceImpl extends IAidlServiceInterface.Stub {
    @Override
    public String getMessages() throws RemoteException {
        return "This is the AIDL ServiceClient message!";
    }

    @Override
    public void sendMessageToService(String message) throws RemoteException {
        Log.i("===========>", "service receive :" + message);
    }
}

 

在客户端的AIDL文件里添加和服务端相同的void sendMessageToService(String message)方法,记得Sync Project

// IAidlServiceInterface.aidl
package com.fanxb.aidlserviceclient;

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

interface IAidlServiceInterface {
    String getMessages();
    void sendMessageToService(String message);
}

将ClientApplication 的绑定方法取消,在客户端的MainActivity类里添加四个按钮,分别为 bindServie、unbinService、getMessage、sendMessageToService四个点击事件。

 

绑定服务:

private void bindService() {
    Intent intent = new Intent();
    intent.setAction("com.fanxb.aidlserviceclient.service");
    intent.setPackage("com.fanxb.aidlserviceclient");
    bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
}

/**
 * Service Connection callback
 */
private ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        sIAidlServiceInterface = IAidlServiceInterface.Stub.asInterface(iBinder);
        Log.i("===========>", "Server connected successfully!!!");
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Log.i("==============>", "onServiceDisconnected!!!");
        sIAidlServiceInterface = null;
    }
};

 

获取消息:

if (sIAidlServiceInterface != null) {
    try {
        String message = sIAidlServiceInterface.getMessages();
        Log.i("============>", "client getMessage:" + message);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

 

发送消息至服务端

if (sIAidlServiceInterface != null) {
    try {
        sIAidlServiceInterface.sendMessageToService("this is client send message!!!");
    } catch (RemoteException e) {
        e.printStackTrace();
    }
} else {
    Log.i("============>", "sIAidlServiceInterface is null");
}

解绑:

if (sIAidlServiceInterface != null) {

    unbindService(mServiceConnection);

    sIAidlServiceInterface = null;
}

 

打印信息:

以上介绍的是正常情况下的操作,如果出现连接通信过程中,出现连接异常,断开了通信,如何操作呢?

 

四、Binder 死亡代理

Binder类中比较重要的两个方法linkToDeath和unlinkToDeath。Binder是运行在服务进程,若服务端进程因为某种原因“死亡”,那么Binder对象也将随之而去,因为Binder对象是寄宿在服务端进程中的,这个时候我们的远程调用将会失败,客户端进程的功能也将受到影响。Binder类提供linkToDeath方法在客户端可以设置死亡代理,当服务端的Binder对象“死亡”,客户端可以受到死亡通知,这个时候我们可以重新恢复链接。

private ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        sIAidlServiceInterface = IAidlServiceInterface.Stub.asInterface(iBinder);
        Log.i("===========>", "Server connected successfully!!!");
        try {
            //设置Binder死亡代理
            sIAidlServiceInterface.asBinder().linkToDeath(mDeathRecipient, 0);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Log.i("==============>", "onServiceDisconnected!!!");
    }
};

private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    @Override
    public void binderDied() {
        if (null == sIAidlServiceInterface) {
            return;
        }
        sIAidlServiceInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
        sIAidlServiceInterface = null;
        Log.i("========>", "开始重连!");
        bindService();
    }
};

 

五、callBack回调机制

当客户端向服务端发送消息后,希望得到服务端的结果返回,这里就需要建立callBack机制,实现双向通信。

在服务端AIDL文件夹下新建一个AIDL文件,用于定义回调接口,并声明onSuccess和onFailed方法,这两个方法是用于业务层的,比如服务端接收消息失败时调用onFailed,接收成功调用onSuccess。记得Sync Project

// IICallBackInterface.aidl
package com.fanxb.aidlserviceclient;

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

interface ICallBackInterface {
   void onSuccess(String result);
   void onFailed(String errorMessage);
}

 

修改服务端IAidlServiceInterface文件,新增registerCallBack、unregisterCallBack两个方法,用于客户端注册回调和解除回调,记得Sync Project,同时需要import ICallBackInterface接口的包名。

// IAidlServiceInterface.aidl
package com.fanxb.aidlserviceclient;

// Declare any non-default types here with import statements
import com.fanxb.aidlserviceclient.ICallBackInterface;

interface IAidlServiceInterface {
    String getMessages();
    void sendMessageToService(String message);
    void registerCallBack(ICallBackInterface callBackInterface);
    void unregisterCallBack(ICallBackInterface callBackInterface);
}

 

在服务端的IAidlInterfaceImpl类里重写registerCallBack、unregisterCallBack两个方法,接收客户端注册回调和解除回调。

public class IAidlInterfaceImpl extends IAidlServiceInterface.Stub {
    private RemoteCallbackList<ICallBackInterface> mCallbackList = new RemoteCallbackList<>();

    @Override
    public String getMessages() throws RemoteException {
        return "This is the AIDL ServiceClient message!";
    }

    @Override
    public void sendMessageToService(String message) throws RemoteException {
        Log.i("===========>", "service receive :" + message);
        if (TextUtils.isEmpty(message)) {
            dispatchResult(false, "receive message failed, message isEmpty ");
        } else {
            String msg = message;
            dispatchResult(true, "receive message successfully");
        }
    }

    @Override
    public void registerCallBack(ICallBackInterface callBackInterface) throws RemoteException {
        if (callBackInterface != null) {
            mCallbackList.register(callBackInterface);
        }
    }

    @Override
    public void unregisterCallBack(ICallBackInterface callBackInterface) throws RemoteException {
        if (callBackInterface != null) {
            mCallbackList.unregister(callBackInterface);
        }
    }

  /**
     * 结果分发
     *
     * @param result this is result
     * @param msg    this is msg
     */
    private void dispatchResult(boolean result, String msg) {
        int length = mCallbackList.beginBroadcast();
        for (int i = 0; i < length; i++) {
            ICallBackInterface callBackInterface = mCallbackList.getBroadcastItem(i);
            try {
                if (result) {
                    callBackInterface.onSuccess(msg);
                } else {
                    callBackInterface.onFailed(msg);
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        mCallbackList.finishBroadcast();
    }
}

 

在服务端的AIDL文件复制到客户端,记得Sync Project,在客户端里编辑callBack方法。

ICallBackInterface mICallBackInterface = new ICallBackInterface.Stub() {
    @Override
    public void onSuccess(String result) throws RemoteException {
    }

    @Override
    public void onFailed(String errorMessage) throws RemoteException {

    }
};

 

在绑定服务成功后注册callBack事件。

sIAidlServiceInterface.registerCallBack(mICallBackInterface);

 

取消注册callBack

@Override
protected void onDestroy() {
    super.onDestroy();
    if (null != sIAidlServiceInterface && sIAidlServiceInterface.asBinder().isBinderAlive()) {
        try {
            sIAidlServiceInterface.unregisterCallBack(mICallBackInterface);
            unbindService(mServiceConnection);
            sIAidlServiceInterface = null;
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

结尾:

好了小伙伴们,AIDL的完整使用就是这些了,完整代码地址如下,仅供大家下载参阅。

https://github.com/fanxingbin/MyAIDLDemo

注意事项:

Binder死亡代理只有在非正常断开的情况下才会生效;

每次修改AIDL文件必须Sync Project;

客户端和服务端AIDL文件必须使用同一个;

客户端和服务端AIDL包名路径必须一致;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
AIDLAndroid Interface Definition Language)是Android用于进程间通信(IPC)的一种机制。它允许不的应用程序或在不同的进程进行通信。下面是对AIDL进程间通信的详细讲解: 1. 定义接口:首先,你需要创建一个AIDL接口,该接口包含用于进程间通信的方法和数据类型。AIDL接口文件通常以`.aidl`为后缀名,放置在`src/main/aidl`目录。在接口定义的方法参数和返回值只能使用支持的数据类型、其他AIDL接口或Parcelable对象。 2. 实现接口:在服务端应用程序,你需要实现AIDL接口。实现类需要继承自AIDL接口生成的抽象类,并实现其的方法。这些方法将用于处理客户端发起的远程调用请求。 3. 注册接口:在服务端应用程序的`AndroidManifest.xml`文件使用`<service>`标签注册你的服务,并通过`android:process`属性指定所在的进程。确保在`<intent-filter>`标签包含正确的action,使得客户端能够找到并与你的服务进行绑定。 4. 创建客户端:在客户端应用程序,你需要绑定到服务端应用程序的服务。使用`ServiceConnection`接口来管理与服务的连接和断开连接。当连接成功后,你可以通过AIDL接口提供的方法与服务进行通信。 5. 调用方法:在客户端与服务端建立连接后,你可以通过AIDL接口提供的方法调用服务端的功能。这些方法调用将跨越进程边界执行,并将结果返回给客户端。 6. 处理并发:在处理AIDL进程间通信时,需要注意并发性和线程安全性。多个客户端可能同时访问服务端,因此需要合理地处理并发情况,以保证数据的一致性和安全性。 总结来说,AIDL进程间通信是通过定义接口、实现接口、注册接口、创建客户端和调用方法来实现的。这种机制允许不同进程的应用程序之间进行通信,并共享数据和功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值