当前位置: 首页 > news >正文

Android aidl及binder基础知识巩固

作者:义华

1、什么是binder

binder是android framework提供的,用于跨进程方法调用的机制,具有安全高效等特点。

我们知道,在 Android 系统中,每个应用程序都运行在一个独立的进程中,各个进程之间需要进行数据交换和调用,以实现各种功能。为了实现这个目的,binder应运而生。

2、binder的历史

android基于linux内核,linux提供了非常多的跨进程机制。 为什么android要使用binder而不使用linux已有的ipc机制呢,这个抉择在android内部团队中有过争论。 部分工程师认为binder内部的线程等待带来了系统开销,同时没有显示出更好的用处。 但最后binder还是凭借其优势胜出了。 其实,binder是部分android工程师在PalmSource工作时开源的一种ipc机制,负责开发ipc的工程师直接在此binder上进行了移植和开发。

在《Android传奇》一书中有介绍binder的相关历史。

3、binder基本使用

binder是一种架构,这种架构提供了服务端接口、binder驱动和客户端三个模块。

客户端通过binder远程调用服务端接口,binder驱动负责完成这次远程调用。 在android framework中提供了Binder类,一个类如果扩展Binder类,那么该类就有提供远程服务的能力,该类对象一旦创建,其内部就会创建一个隐藏的线程,用来接收binder驱动发送的消息,从而调用Binder类的onTransact()方法。

binder驱动从表现上看,就是在客户端和服务端传递各种消息,以完成跨进程调用。 在任意一个服务端binder对象创建时,同时也会在binder驱动中创建一个对应的mRemote对象,该对象也是binder类型。 客户端就是通过mRemote对象来访问远程服务的,相当于经过了一层代理。 这种机制提供了更好的安全性。

客户端通过获取远程服务在binder驱动中对应的mRemote对象,通过调用mRemote.transact方法从而实现对远程服务的调用。

从整个架构上看,就是服务端提供binder,binder驱动负责转发消息,客户端获取binder引用并调用。 粗略看很简单,细节是魔鬼。

摘抄一个书中的例子,从demo理解binder的调用过程。 比如要提供一个音乐播放的远程调用, 可以提供一个MusicPlayerService,代码如下:

public class MusicPlayerService extends Binder {public void startPlay(String filePath) {}public void stop() {}@Overridepublic void onTransact(int code, Parcel data, Parcel reply, int flag) {// 这个方法很重要,由binder驱动调用// 根据约定的code值分别调用不同的业务方法,此处是startPlay和stopif (code == 0x100) {this.startPlay(file_path)} else if (code == 0x101) {this.stop()}}
}

如上MusicPlayerService就可以提供了远程调用服务了。 但是客户端如何使用呢。通过binder架构知道,要想远程调用,必须获取远程服务在binder驱动中对应的binder代理对象。此处假设已经获取到相关的引用mRemote,那么客户端便可以如下调用。

IBinder mRemote = null;
String filePath = "xxx";
int code = 0x100;Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain(); // 接收远程调用的结果
data.writeString(filePath);
mRemote.transact(code, data, reply, 0)

如上便完成了客户端对服务端的远程调用。 从这个demo就可以看出跨进程调用其实就是要通过Binder驱动来中转一下调用。 以前没看过这个示例时老是不理解aidl生成的规则,不断的复习也总是记不住规则。但是通过这个示例一下就明白了这个过程,在理解的基础上再去手动编写binder类就水到渠成了(虽然一般也用不到手动去写binder类)。

现在就只剩如何获取远程服务对应的binder对象了。 为了简化这个过程,android frameworks通过service提供这个能力。 在service的生命周期方法中有一个onBind方法返回IBinder对象,方法签名如下:

override fun onBind(intent: Intent?): IBinder? {

在调用context.bindService方法进行绑定时,要求传入一个ServiceConnection的对象,在服务绑定成功时会回调onServiceConnection方法,一并传回服务端的Binder代理对象。 如下:

Intent it = new Intent(this, xxxService.class);
context.bindService(intent, new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// 此处就拿到了远程服务对应的binder了,客户端通过此binder就可以调用远程服务的方法了。 }@Overridepublic void onServiceDisconnected(ComponentName name) {}
}, Service.BIND_AUTO_CREATE);

仔细想想,应用开发好像也只有这么一条路获取服务端的binder。 但是最初我们定义的MusicPlayerService并不是一个真正的service,无法使用bindService方法,故需要改造一下,让MusicPlayerService继承Service类。 如下:

public class MusicPlayerService extends Service {private XXXBinder mBinder;@Overridepublic IBinder onBind(Intent intent) {return mBinder;  // 此处返回服务端的binder}public void startPlay(String filePath) {}public void stop() {}// 由于android应用开发上只能通过service进行远程调用,故在service内部类创建binder,方便调用service定义的业务方法。 public xxxBinder extends Binder {@Overridepublic void onTransact(int code, Parcel data, Parcel reply, int flag) {// 这个方法很重要,由binder驱动调用// 根据约定的code值分别调用不同的业务方法,此处是startPlay和stopif (code == 0x100) {startPlay(file_path)} else if (code == 0x101) {stop()}}}
}

由于java不能多继承,继承了service类就不能继承Binder类了。 那么可以在MusicPlayerService类内部构建一个内部类,继承binder,并通过onBind返回binder对象给客户端。 这个代码架构便是使用binder的基本雏形了。但是,在日常开发过程中,为了扩展性和解耦,一般将业务方法通过接口抽象出来。 如下抽象出播放接口。

public interface IPlayer {public void startPlay(String filePath);public void stop();
}

通过上面的代码可以发现,播放的实现放在XXXBinder类或者MusicPlayerService都是可行的。 为了方便binder调用业务方法,尝试用binder实现接口并实现业务。 改造后的代码如下:

public class MusicPlayerService extends Service {private XXXBinder mBinder;@Overridepublic IBinder onBind(Intent intent) {return mBinder;  // 此处返回服务端的binder}// binder实现了IPlayer业务接口public xxxBinder extends Binder implemention IPlayer {@Overridepublic void onTransact(int code, Parcel data, Parcel reply, int flag) {// 这个方法很重要,由binder驱动调用// 根据约定的code值分别调用不同的业务方法,此处是startPlay和stopif (code == 0x100) {this.startPlay(file_path)} else if (code == 0x101) {this.stop()}}public void startPlay(String filePath) {Log.i("test", "startPlay");}public void stop() {Log.i("test", "stop");}}
}

至此,使用binder的代码结构就较为清晰了。以上demo一步步的改造,其实就是为了更加深刻的理解binder的使用,并向aidl靠拢,从而更好的理解aidl生成的代码。 从上代码可以看出,使用binder的代码接口基本是固定的,所以android framewrok提供了一个aidl的工具来简化这个过程。

4、aidl的使用

在对应模块上右键选择aidl,会弹出创建aidl的对话框,输入名字as会自动生成对应的aidl文件。 在aidl文件中加入自己的业务接口即可。 build一下as就会根据aidl自动生成相应的接口类和binder类,具体文件此处省略。

需要注意的是,aidl中只支持Parcelable对象和原子类,如果有自定义的类需要跨进程访问时需要实现Parcelable接口。

客户端通过如下代码获取接口对象并实现调用。

class MusicClient {private var mIMusicPlayer: IMusicPlayer? = nullprivate var mServiceConnection = object: ServiceConnection {override fun onServiceConnected(name: ComponentName?, service: IBinder?) {// 这个方法中提供了是本地通信还是跨进程通信的判断// 这里就客户端进程就获取了远程服务的binder引用了。 aidl工具生成了Stub及Proxy类封装了直接通过binder.transact调用的逻辑,让开发者只需和接口交互即可。 不必关心binder交互的细节。 mIMusicPlayer = IMusicPlayer.Stub.asInterface(service)}override fun onServiceDisconnected(name: ComponentName?) {}}fun bindMusicService(context: Context) {val intent = Intent(context, PlayerService::class.java)context.bindService(intent, mServiceConnection, Service.BIND_AUTO_CREATE)}
}

注意在使用aidl时,如果客户端和服务端在不同的工程时,两端的aidl文件要是一样的。实际中可以直接拷贝。

5、binder架构

此处摘抄一张binder架构图

从这张图就可以清晰看到客户端、驱动及服务端的职责,也能更好的理解binder的交互过程。这么看下来,感觉binder驱动其实就是负责对消息进行了转发,同时对交互的过程进行了一定控制。

6、总结

1.一个类要想序列化就要实现Serializable或Parcelable接口,同理一个类要想提供跨进程服务,就必须继承binder类。 binder就像一个标记类一样,只要继承了,就有资格在进程间通信了。
2.一个binder跨进程的通信包含了客户端、服务端和binder驱动三方。
3.在应用开发中主要通过aidl工具、Service及Context.bindService实现跨进程访问。
4.aidl是一个命令行工具,协助生成跨进程调用的样板代码。

想了解Framework底层知识点的小伙伴可以参考一下,在学习过程中我也查阅和收集了一堆的参考学习文档,比如有Handler、Binder、AMS、WMS、PMS、事件分发机制、UI绘制……等等,为了便于自己查阅,将其知识点整合在一起并命名为了《Android Framework 核心学习手册》:https://qr18.cn/AQpN4J

《Framework 核心知识点汇总手册》:https://qr18.cn/AQpN4J

Handler 机制实现原理部分:
1.宏观理论分析与Message源码分析
2.MessageQueue的源码分析
3.Looper的源码分析
4.handler的源码分析
5.总结

Binder 原理:
1.学习Binder前必须要了解的知识点
2.ServiceManager中的Binder机制
3.系统服务的注册过程
4.ServiceManager的启动过程
5.系统服务的获取过程
6.Java Binder的初始化
7.Java Binder中系统服务的注册过程

Zygote :

  1. Android系统的启动过程及Zygote的启动过程
  2. 应用进程的启动过程

AMS源码分析 :

  1. Activity生命周期管理
  2. onActivityResult执行过程
  3. AMS中Activity栈管理详解

深入PMS源码:

1.PMS的启动过程和执行流程
2.APK的安装和卸载源码分析
3.PMS中intent-filter的匹配架构

WMS:
1.WMS的诞生
2.WMS的重要成员和Window的添加过程
3.Window的删除过程

《Android Framework学习手册》:https://qr18.cn/AQpN4J

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战

相关文章:

Android aidl及binder基础知识巩固

作者:义华 1、什么是binder binder是android framework提供的,用于跨进程方法调用的机制,具有安全高效等特点。 我们知道,在 Android 系统中,每个应用程序都运行在一个独立的进程中,各个进程之间需要进行…...

[日记]LeetCode算法·二十五——二叉树⑤ AVL树(插入+删除)附代码实现

本章的代码实现基于上一篇BST与优先队列的基类进行平衡二叉树,即AVL树。 文章目录 AVL的概念AVL查询效率AVL的插入1.插入节点2.更新平衡因子BF3.旋转调整树的结构3.1 LL 右旋3.2 RR 左旋3.3 LR 左右双旋3.4 RL 右左双旋 4 插入总结 AVL的删除1.寻找删除节点2.更新平…...

flink-1.13.6 例子

-------------------------------------------------------------- flink版本: flink-1.13.6 [rootmaster bin]# pip3 list | grep flink WARNING: Ignoring invalid distribution -andas (/usr/local/python38/lib/python3.8/site-packages) apache-flink 1.13.0 a…...

Go语音基于zap的日志封装

zap日志封装 Zap是一个高性能、结构化日志库,专为Go语言设计。它由Uber开源,并且在Go社区中非常受欢迎。它的设计目标是提供一个简单易用、高效稳定、灵活可扩展的日志系统。 以下是Zap的一些主要特点: 1.高性能:Zap的性能非常出…...

可持续能源技术具有改变世界的潜力,并且已经在多个方面展现出积极的影响。

可持续能源技术的发展在当今全球面临的气候变化和能源安全挑战中扮演着至关重要的角色。我认为可持续能源技术具有改变世界的潜力,并且已经在多个方面展现出积极的影响。以下是我对此的观点: 1,可持续能源技术有助于减少对化石燃料的依赖 化…...

Java常用工具之StringUtils类

目录 一、字符串判空二、分隔字符串三、判断是否为纯数字四、将集合拼接成字符串五、其他方法 字符串(String)在我们的日常工作中,用得非常非常非常多。 在我们的代码中经常需要对字符串判空,截取字符串、转换大小写、分隔字符串、…...

MyBatis-plus的批量插入方式对比分析

MyBatis-plus的批量插入方式对比分析 【摘要】Mybatis批量插入一直是开发者重点关注的问题&#xff0c;本文列举了Mybatis的五种插入方式进行对比分析&#xff0c;验证了五种批量插入的方式的优先级。 1 准备工作 1.1 新建spring项目 略。 1.2 导入pom.xml依赖 <depende…...

【系分论文】论软件开发模型及应用

目录 论题论题介绍论文要点理论素材准备范文摘要正文 论文补充知识 论题 论软件开发模型及应用 论题介绍 软件开发模型&#xff08; Software Development Model&#xff09;是指软件开发全部过程、活动和任务的结构框架。软件开发过程包括需求、设计、编码和测试等阶段&…...

渗透测试--5.3.使用john破解密码

前言 由于Linux是Internet最流行的服务器操作系统&#xff0c;因此它的安全性备受关注。这种安全主要靠口令实现。 Linux使用一个单向函数crypt&#xff08;&#xff09;来加密用户口令。单向函数crypt&#xff08;&#xff09;从数学原理上保证了从加密的密文得到加密前的明…...

Go中的变量类型

Go中的变量类型 1.为什么要使用变量 变量其实指定的是一段内存地址&#xff0c;根据这个内存地址可以找到我们需要找到的东西。 2.变量类型 变量的功能就是用来存储数据的&#xff0c;根据不同的数据类型可以存储不同的数据。常见的变量的类型 整型、浮点型、布尔型等。变…...

基于STM32的NRF24L01 2.4G通讯模块的驱动实验(HAL库)

前言&#xff1a;本文为手把手教学NRF24L01 2.4G通讯模块的驱动实验&#xff0c;本教程的 MCU 采用STM32F103ZET6与STM32F103C8T6&#xff0c;彼此进行互相通讯。通过 CubeMX 软件配置 SPI 协议驱动NRF24L01 2.4G通讯模块&#xff08;HAL库&#xff09;。NRF24L01 2.4G是嵌入式…...

DJ5-3 多路访问链路和协议

目录 一、网络链路 二、广播信道要解决问题 三、多路访问协议 1、基本介绍 2、多路访问协议的类型&#xff08;3&#xff09; 四、信道划分协议 1、时分多路访问 TDMA 2、频分多路访问 FDMA 3、码分多路访问 CDMA&#xff08;略&#xff09; 五、随机访问协议 1、纯…...

技术领导力?

作品集&#xff08;Portfolio&#xff09;会比简历&#xff08;Resume&#xff09;更有参考意义。 怎么才算有技术领导力&#xff1f; 1) 能够发现问题&#xff0c;并能够提供解决问题的思路和方案&#xff0c;并能比较方案的优缺点。 2) 能用更简洁有效的方式解决问题。 3…...

计算机的基本工作原理

参考资料&#xff1a; L-1.6: Common Bus system| How basic computer works - YouTube 准备好内存单元、不同类型的寄存器&#xff0c;内存和寄存器、寄存器和寄存器之间都是通过总线连接(假设是直接把数据总线、控制总线、地址总线变成一条总线)。 使用多路复用器实现的总线&…...

【论文简述】Cross-Attentional Flow Transformer for Robust Optical Flow(CVPR 2022)

一、论文简述 1. 第一作者&#xff1a;Xiuchao Sui、Shaohua Li 2. 发表年份&#xff1a;2021 3. 发表期刊&#xff1a;arxiv 4. 关键词&#xff1a;光流、Transformer、自注意力、交叉注意力、相关体 5. 探索动机&#xff1a;由于卷积的局部性和刚性权重&#xff0c;有限…...

【JAVA】Java中方法的使用,理解方法重载和递归

目录 1.方法的概念及使用 1.1什么是方法 1.2方法的定义 1.3方法调用的执行过程 1.4实参和形参 2.方法重载 2.1为什么需要使用方法重载 2.2什么是方法重载 3.递归 3.1什么是递归 3.2递归执行的过程 3.3递归的使用 1.方法的概念及使用 1.1什么是方法 方法就是一个代…...

高级网络计算模式复习

P2P 对等网络&#xff08;Peer-to-Peer Networks&#xff09;是分布式系统和计算机网络相结合的产物&#xff0c;在应用领域和学术界获得了广泛的重视和成功&#xff0c;被称为“改变Internet的一代网络技术”。 peer指网络结点&#xff0c;在行为上是自由的——任意加入、退…...

【笔试强训选择题】Day15.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01; 文章目录 前言 一、…...

图论专题(一)

图论专题(一) 参考文献 BFS和DFS的直观解释 https://blog.csdn.net/c406495762/article/details/117307841Leetcode岛屿问题系列分析 https://blog.csdn.net/qq_39144436/article/details/124173504多源广度优先 https://blog.csdn.net/peko1/article/details/121989497拓扑排…...

新星计划2023【网络应用领域基础】————————Day4

常见的网络基础介绍 前言 我们学习了一些基础的网络协议&#xff0c;以及子网掩码和vlan&#xff0c;同时也做了个简单的单臂路由实验 这篇文章我将仔细的讲解单臂路由的应用和交换机二层接口类型&#xff0c;以及wireshark的教程。 一&#xff0c;交换机二层接口 交换机的二…...

如何理解InnoDB的行级锁_记录锁与间隙锁Gap Lock的区别

Record Lock锁存在行&#xff0c;Gap Lock锁不存在的索引间隙&#xff1b;前者为点锁&#xff0c;后者为段锁&#xff0c;仅在REPEATABLE READ生效&#xff0c;Next-Key Lock是其与记录锁组合&#xff0c;用于防止幻读。Record Lock 锁的是“存在的行”&#xff0c;Gap Lock 锁…...

Qt 6实战:用Q3DScatter在C++中实现动态3D点云可视化(附完整源码)

Qt 6实战&#xff1a;用Q3DScatter在C中实现动态3D点云可视化&#xff08;附完整源码&#xff09; 在工业测量、自动驾驶和科学计算领域&#xff0c;3D点云可视化正成为数据交互的核心需求。当我们需要处理激光雷达扫描、三维重建或流体动力学模拟产生的海量空间数据时&#xf…...

Qwen3.5-9B代码生成效果:单元测试自动生成+边界条件覆盖分析

Qwen3.5-9B代码生成效果&#xff1a;单元测试自动生成边界条件覆盖分析 1. 开篇&#xff1a;认识Qwen3.5-9B代码生成能力 Qwen3.5-9B是一款拥有90亿参数的开源大语言模型&#xff0c;在代码生成领域展现出惊人的能力。不同于普通代码补全工具&#xff0c;它能理解复杂编程逻辑…...

终极ARC-AGI测试功能扩展指南:从零开始自定义AI推理任务

终极ARC-AGI测试功能扩展指南&#xff1a;从零开始自定义AI推理任务 【免费下载链接】ARC-AGI The Abstraction and Reasoning Corpus 项目地址: https://gitcode.com/GitHub_Trending/ar/ARC-AGI 欢迎来到ARC-AGI&#xff08;Abstraction and Reasoning Corpus for Art…...

使用钉钉远程操作你的claude code寺

先回顾&#xff1a;三次握手&#xff08;建立连接&#xff09;核心流程&#xff08;实际版&#xff09; 为了让挥手流程衔接更顺畅&#xff0c;咱们先快速回顾三次握手的实际核心&#xff0c;避免上下文脱节&#xff1a; 第一步&#xff08;客户端→服务器&#xff09;&#xf…...

深入解析AMD Versal自适应SoC:架构革新与多场景应用指南

1. 什么是AMD Versal自适应SoC&#xff1f; 第一次接触Versal自适应SoC时&#xff0c;我完全被它的设计理念震撼到了。这不像传统FPGA那样只是可编程逻辑的堆砌&#xff0c;也不像普通SoC那样固定架构。它更像是一个"变形金刚"&#xff0c;能根据不同的应用场景动态调…...

环形缓冲区(Ring Buffer)

文章目录1. 环形缓冲区工作流程2. C 语言实现2.1 头文件 ringbuf.h&#xff08;RINGBUF_SIZE256&#xff09;2.2 源文件 ringbuf.c3. 在串口中断服务函数中使用示例4. 临界区保护说明5. 总结1. 环形缓冲区工作流程 写入流程 (ISR中调用)&#xff1a; #mermaid-svg-j444GbsyedL…...

AI医学影像领域标杆推荐:德适

医学影像作为AI落地最成熟、临床价值最明确的赛道&#xff0c;正迎来从单点工具向通用大模型跃迁的关键阶段。德适以自主可控的底层技术、深度贴合临床的产品矩阵与规模化商业兑现能力&#xff0c;成为2026年AI医学影像领域最值得重点关注的标杆企业。 德适是国家级专精特新“小…...

做了一个网页天气可视化路

基础示例&#xff1a;单工作表 Excel 转 TXT 以下是将一个 Excel 文件中的第一个工作表转换为 TXT 的完整步骤&#xff1a; 1. 加载并读取Excel文件 from spire.xls import * from spire.xls.common import * workbook Workbook() workbook.LoadFromFile("示例.xlsx"…...

MIT Cheetah机器人刚体模型详解:从DH参数到足端位置计算的保姆级推导

MIT Cheetah机器人刚体建模实战&#xff1a;从坐标系定义到足端轨迹计算的完整推导 在四足机器人研究领域&#xff0c;MIT Cheetah系列机器人以其卓越的运动性能和创新设计闻名。对于想要深入理解其运动控制原理的工程师和学生来说&#xff0c;掌握其刚体建模方法是必经之路。本…...