文章目录

  • AIDL 跨进程通信完整流程梳理
    • 1、AIDL 文件编译
    • 2、注册服务
    • 3、IMyAidlInterface.Stub.asInterface 方法获取远程服务
    • 4、IMyAidlInterface.Stub.Proxy 代理类
    • 5、IMyAidlInterface.Stub.Proxy 代理类方法执行
    • 6、Binder.transact 方法执行
    • 7、IMyAidlInterface.Stub.onTransact 方法执行
    • 8、调用 Service 中实现的 IMyAidlInterface.Stub 抽象方法

AIDL 跨进程通信完整流程梳理


1、AIDL 文件编译

AIDL 文件 IMyAidlInterface.aidl 在客户端和服务端都有 , 编译时 , 都会在 " build\generated\aidl_source_output_dir\debug\out\kim\hsl\aidl_demo " 目录生成 IMyAidlInterface.java 源文件 ;

这样在客户端与服务器端都可以调用 IMyAidlInterface.Stub 类的相关方法 , 主要是 asInterface 方法 , 用于获取远程服务或代理 ;

2、注册服务

在应用中 , 通过绑定 Service 注册服务 ;

        // 通过 Action 和 包名 , 绑定远程服务Intent intent = new Intent("android.intent.action.MyService");intent.setPackage("kim.hsl.aidl_demo");bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

3、IMyAidlInterface.Stub.asInterface 方法获取远程服务

开启一个 ServiceConnection , 在 ServiceConnectiononServiceConnected 方法中 ,

调用 IMyAidlInterface.Stub.asInterface 方法 ,

IMyAidlInterface.Stub.asInterface 方法中 , 传入我们需要的 Service 远程服务 ; 这里涉及到跨进程调用 , 拿到的是一个代理 ;

Stub 中定义了 asInterface 方法 , 该方法的作用是将 android.os.IBinder 对象转为 AIDL 接口对象 ; 传入的 DESCRIPTOR 描述符 , 用于描述用户想要哪个 Binder , android.os.IBinder 对象调用 queryLocalInterface 方法 , 检查本地服务是否存在 ;

  • 如果可以找到本地服务对应的接口 , 可以直接返回本地服务 ;
  • 如果没有找到本地服务 , 就会返回一个 Stub 代理 ;

详细的过程参考下面的代码 :

    /*** 将IBinder对象强制转换为kim.hsl.aidl_demo.IMyAidlInterface接口,必要时生成代理。*/public static kim.hsl.aidl_demo.IMyAidlInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}// 传入 DESCRIPTOR 描述符 , 用于描述用户想要哪个 Binder// android.os.IBinder 对象调用 queryLocalInterface 方法 , 检查本地服务android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);// 如果可以找到本地服务对应的接口 , 可以直接返回本地服务 if (((iin!=null)&&(iin instanceof kim.hsl.aidl_demo.IMyAidlInterface))) {return ((kim.hsl.aidl_demo.IMyAidlInterface)iin);}// 如果没有找到本地服务 , 就会返回一个 Stub 代理 return new kim.hsl.aidl_demo.IMyAidlInterface.Stub.Proxy(obj);}

4、IMyAidlInterface.Stub.Proxy 代理类

上述 IMyAidlInterface.Stub.asInterface 方法 , 最终返回一个代理 , 代理如下 :

在 IMyAidlInterface.java 中的代理中 , 实现了 333 个 AIDL 接口方法 ;

    private static class Proxy implements kim.hsl.aidl_demo.IMyAidlInterface{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException{}/*** in 写入, out 输出, inout 写入和输出*/@Override public void addStudent(kim.hsl.aidl_demo.Student student) throws android.os.RemoteException{}/*** 获取 Student 集合*/@Override public java.util.List<kim.hsl.aidl_demo.Student> getStudents() throws android.os.RemoteException{return _result;}}

5、IMyAidlInterface.Stub.Proxy 代理类方法执行

在主应用中 , 调用 IMyAidlInterface aidl 也就是 IMyAidlInterface.Stub.asInterface 方法返回的代理对象的 addStudent 方法 , 分析代理中的该方法 , 首先生成输入和输出数据 , 传参和反参都会传入 mRemote.transact 方法中 , 这是 Binder 的方法 ;

      /*** in 写入, out 输出, inout 写入和输出*/@Override public void addStudent(kim.hsl.aidl_demo.Student student) throws android.os.RemoteException{// 通过 Parcel 池获得两个对象 , 分别用于输入和输出// 输入对象android.os.Parcel _data = android.os.Parcel.obtain();// 输出对象android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);if ((student!=null)) {_data.writeInt(1);student.writeToParcel(_data, 0);}else {_data.writeInt(0);}// 调用 Binder 的 transact 方法 boolean _status = mRemote.transact(Stub.TRANSACTION_addStudent, _data, _reply, 0);if (!_status && getDefaultImpl() != null) {getDefaultImpl().addStudent(student);return;}_reply.readException();if ((0!=_reply.readInt())) {student.readFromParcel(_reply);}}finally {_reply.recycle();_data.recycle();}}

6、Binder.transact 方法执行

Binder 中的 transact 方法执行后 , 会回调 IMyAidlInterface.java 中的 Stub 内部类的 onTransact 方法 ,

Binder 的 transact 方法 ; 进入该方法后 , 会将原来的线程挂起 , 直到返回 , 原来的线程才会继续执行 , 这里非常容易出现 ANR ;

/*** 远程对象的基类,由{@link IBinder}定义的轻量级远程过程调用机制的核心部分。* 此类是IBinder的一个实现,它提供了此类对象的标准本地实现。** <p>大多数开发人员不会直接实现这个类,* 而是使用<a href=“{@docRoot}guide/components/aidl.html”>aidl</a>工具来描述所需的接口,* 让它生成适当的Binder子类。* 然而,您可以直接从Binder派生来实现您自己的定制RPC协议,* 或者直接实例化一个原始Binder对象,将其用作可以跨进程共享的令牌。** <p>这个类只是一个基本的IPC原语;* 它对应用程序的生命周期没有影响,并且只有创建它的进程继续运行时才有效。* 要正确使用此功能,您必须在顶级应用程序组件(a{@link android.app.Service}、* {@link android.app.Activity}或{@link android.content.ContentProvider})* 的上下文中执行此操作,该组件应保持运行。</p>** <p>您必须记住流程可能会消失的情况,因此需要稍后重新创建新的活页夹,* 并在流程再次启动时重新附加它。* 例如,如果您在{@link android.app.Activity}中使用此函数,* 则您的活动的进程可能会在活动未启动时被终止;* 如果以后重新创建活动,则需要创建新的活页夹,* 并再次将其交回正确的位置;* 您需要注意的是,您的流程可能由于其他原因(例如接收广播)而启动,* 这将不涉及重新创建活动,因此运行其代码以创建新的绑定。</p>** @see IBinder*/
public class Binder implements IBinder {/*** 默认实现回放地块并调用onTransact。在远程端,transact调用绑定器来执行IPC。*/public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,int flags) throws RemoteException {if (false) Log.v("Binder", "Transact: " + code + " to " + this);if (data != null) {data.setDataPosition(0);}boolean r = onTransact(code, data, reply, flags);if (reply != null) {reply.setDataPosition(0);}return r;}
}

7、IMyAidlInterface.Stub.onTransact 方法执行

IMyAidlInterface.Stub.onTransact 方法中 , 通过方法对应的 ID 常量值匹配方法 , 在该方法中就会调用 IMyAidlInterface.Stub 中没有实现的抽象方法 ;

    @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{java.lang.String descriptor = DESCRIPTOR;switch (code){case INTERFACE_TRANSACTION:{reply.writeString(descriptor);return true;}case TRANSACTION_basicTypes:{return true;}case TRANSACTION_addStudent:{return true;}case TRANSACTION_getStudents:{return true;}default:{return super.onTransact(code, data, reply, flags);}}}

8、调用 Service 中实现的 IMyAidlInterface.Stub 抽象方法

IMyAidlInterface.Stub 中的抽象方法 , 在 Service 中实现 ;

    /*** 创建 IMyAidlInterface.Stub 抽象类子类对象 , 实现其中的 3 个抽象方法* Binder 调用 transact 方法时 , 会调用 IMyAidlInterface.Stub 的 onTransact 方法* 在 IMyAidlInterface.Stub.onTransact 方法中会调用下面实现的抽象方法*/private IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub() {@Overridepublic void basicTypes(int anInt, long aLong,boolean aBoolean, float aFloat, double aDouble,String aString) throws RemoteException {Log.i(TAG, "anInt=" + anInt + " , aLong=" + aLong +" , aBoolean=" + aBoolean + " , aFloat=" + aFloat +" , aDouble=" + aDouble + " , aString=" + aString);}@Overridepublic void addStudent(Student student) throws RemoteException {if (students != null) {students.add(student);}}@Overridepublic List<Student> getStudents() throws RemoteException {return students;}};

【Binder 机制】AIDL 分析 ( AIDL 通信完整流程梳理 )相关推荐

  1. binder机制原理分析(一):ServiceManager 进程启动

    binder机制原理分析一共分5个部分,其实省了一点,但是分析到后面都差不多了,以后再补充吧. 1.ServiceManager 进程启动 2.普通Service注册到ServiceManager 3 ...

  2. Android Binder机制浅析及AIDL的使用

    参考 轻松理解 Android Binder,只需要读这一篇 图文详解 Android Binder跨进程通信的原理 Android中的Parcel是什么 Android Binder IPC通信机制 ...

  3. app与后台通信完整流程

    前言: 接着补充app后台(也叫服务端开发)的基础知识.基础要夯实,不然哪来的万张高楼? 正文: 问1:整个前台后台交互的流程是个什么样子? 答:基于http协议的app前后台交互包含以下几个步骤: ...

  4. 如何在云服务器上搭建一个自己的博客系统(完整流程梳理)

    文章目录 前言 一.项目下载 1.下载地址: 1.下载及导入本地. 二.搭建前的准备工作. 1.Mysql建库,执行数据库建表,生成数据脚本 2.将博客项目打成jar包. 3.创建项目目录及上传项目配 ...

  5. 一文分析Binder机制和AIDL的理解

    为什么要去理解Android的进程间通信机制 对于Android开发工程师来说,如果不去理解进程间通信机制也可以使用系统提供的API完成应用开发,但如果想要达到更高的层级,那么就不能简单只会调用API ...

  6. Android Binder机制情景源码分析之Binder回调注册和反注册

    我们在日常开发中,经常用到Binder来进行跨进程通信,有个比较常见的场景是向服务端注册Binder回调,比如: IActivityManager中有两个成对的方法,Client端向AMS所在的服务端 ...

  7. 【Binder 机制】Native 层 Binder 机制分析 ( service_manager.c | 开启 Binder | 注册 Binder 进程上下文 | 开启 Binder 循环 )

    文章目录 一.系统服务 二.系统服务主函数 三.开启 Binder 四.注册上下文 五.开启 Binder 循环 六.binder_write 方法 七.binder_ioctl 内核方法 八.bin ...

  8. Android Binder机制(1):Binder架构分析

    从这篇博客开始,将进入Binder机制的分析系列,顺序是先讲解Binder机制的框架,理解了整体思想后,再深入分析各层的细节实现,最后会实现一个自己的本地服务. 1.Binder的历史 BeOS是Be ...

  9. Android跨进程通信Binder机制与AIDL实例

    文章目录 进程通信 1.1 进程空间划分 1.2 跨进程通信IPC 1.3 Linux跨进程通信 1.4 Android进程通信 Binder跨进程通信 2.1 Binder简介 2.2 Binder ...

最新文章

  1. Linux中errno使用
  2. 面向对象入门2--继承
  3. mapreduce.job.reduce.slowstart.completedmaps
  4. IOS开发笔记7-C语言基础复习
  5. 嵌入式成长轨迹11 【嵌入式环境及基础】【Linux shell深入】【深入讨论】
  6. 实施工程师或技术支持应该熟悉的技能
  7. 论文浅尝 - CIKM2021 | DT-GCN: 一种双曲空间中的数据类型感知的知识图谱表示学习模型...
  8. python可以实现的小游戏_今天教小白用Python实现一款小游戏!最适合装逼的神技!亲测可用...
  9. Android 系统(149)---如何初步定位异常关机问题
  10. 顶级域名和二级域名共享cookie及相互删除cookie
  11. 正则表达式 相关教程
  12. matlab3维b样条曲线_MATLAB-3次B样条
  13. pytorch模型转onnx Exporting the operator _thnn_fused_lstm_cell to ONNX opset version 9 is not supported
  14. 办公自动化oa按计算机分类,办公室自动化oa按计算机分类属于什么
  15. 第二天:Kafka API操作
  16. 海马玩模拟器 修改host(让hosts生效)
  17. 三维地图之cesium轨迹回放(有代码)
  18. 用密钥激活win10显示无法连接到你的组织的激活服务器0xc004f074
  19. BP神经网络设计与实现
  20. linux服务器用lighttpd+mysql5+php5+SupeSite/X-Space+discuz构建社区门户

热门文章

  1. Cisco 交換機命名規則
  2. 实践周java基础软件开发app之五子棋
  3. 通过angular.js实现MVC的基本步骤
  4. MPSOC之3——centos环境配置及petalinux安装及使用
  5. JavaEE 的基本实现
  6. bzoj 2190: [SDOI2008]仪仗队 线性欧拉函数
  7. Java--23种设计模式之decorator模式
  8. PHP 函数dirname()使用实例
  9. ZeroClipboard 和JqueryUI_dialog 完美组合!
  10. Visual Studio 2010Beta与Silverlight的更新