从技术角度看Android大系统的构成

news2025/1/13 2:49:27

最近因为工作需要,再次捡起了放下多年的Android开发。说起Android,还是要感谢这个时代,感谢开源。这个时代,让我们开发者,可以通过开源,通过开源的Android,学到很多东西。有如此感慨,是因为早期,像操作系统这类软件,是被厂商严格保护起来的“秘籍”。曾几何时,想学都没有东西学,振臂高呼:“我要学”,是何等的悲壮。现如今,网上一抓一大把的资料,倒不见当年的学习热情,悲乎哉?

 

参加工作十几年来,主要方向一直在嵌入式领域。Android也可以看做是嵌入式大家庭的一员。做Android开发,并没有脱离嵌入式这个大方向。我曾经将嵌入式开发分成了三个大类,如下图所示(参见博文基于多进程架构的嵌入式软件框架研究与实现_龙赤子的博客-CSDN博客_多进程软件架构):

可见,Android也是其中重要的一类。其实,上图的高中低端横轴表述并不正确,简单到复杂的纵轴也不准确。经过很多项目的锤炼后,我认为,更多以业务和需求来做划分基准,是比较靠谱的。这样来看,Android其实是属于消费级的富媒体设备。硬件性能较低、内存较少的这种,包括单片机一类的,则更多面向低功耗、特定功能场景。有些硬实时、高可靠、高安全要求的产品,不见得简单。比如,面向航空航天、汽车等领域的专用功能产品。在这两类之间的,则是功能要求可能没Android那么多,实时性也没有航空航天那样高,通过综合功能、成本等因素,选择比较适中的软硬复杂度构建的嵌入式产品。

纠正了之前的错误后,再来说说Android。重新捡起Android开发,是因为遇到了一个项目上的问题。之前的产品系列中包含有一个Android的APP,可以与我们的后台系统互联互通,这个APP算是补全了终端产品这块的拼图。后来,因为市场因素,这个APP一直没有再维护,至今算起来,已有五六年时间了。最近,新的交付项目又突然包含了这样一个产品,但是客户的硬件(类似手机的便携设备)是基于较新的Android系统开发的,而我们的APP因为开发年代久远,还是基于很老的Android4完成的。结果,老的APP安装到新的硬件上,出现了一些问题。源于此,我又开始着手熟悉Android开发,以便解决该适配问题。一切皆由此开始。

熟悉Android的过程中,发现了很多有意思的东西,也有了很多新的感受,记录于此,是为学习笔记。

首先,Android作为一个系统,一直在演化。可以说,现在的Android,从上到下,从内到外,都发生了很大变化。我们来详细说说。从上到下,是从层级的角度来看。大家都知道,Android包含如下几个层:应用层、框架层、库层、硬件抽象层、内核层、硬件层。这从Google官方释放的结构图就可以看到(https://developer.android.google.cn/guide/platform)。

一个经典的系统层次构成图

关于这几个层次,之前的博文里已经讲解过了,官方文档里也有说明,这里就不再展开。我们说说前面所提的从上到下的变化。首先是应用层,最开始做Android开发时,使用了Eclipse作为IDE。开发语言使用了Java。这些都是可用理解的,因为那时,Google急于推出Android系统,还来不及处理这些事情,于是就使用基于插件设计思想的Eclipse,构建了自家的IDE。这些年,Android系统已经成为移动领域装机最多的系统,地位的稳固性不再是问题,此时,系统生态构建的问题就逐渐提上日程,Google也可以腾出精力将资源投向这块。最终结果是,重新基于Ideal构建了Android Studio作为IDE,研发了Kotlin语言。框架层,SDK的更新是持续进行的。根据技术发展形势,很多新的API不断加入其中。比如,这两年人工智能在端边云大放异彩,Android也适时加入了机器学习相关的API。库层,NDK也在持续的优化更新。最近了解相关资料,我才发现,新的NDK将GCC移除了,采用了更高效、更节省空间的CLANG作为编译工具。C/C++标准库、STL库也被替换了。这其中的每一项,都不是一个简单的任务,都是关系基础根基的,国内在这些方面的积累还是很缺乏。再往下,就是内核层。最开始,Google在内核里添加了不少特性,特别是binder驱动,以此提供便捷高效的进程间通信框架。这两年,据传Google也研发了新的操作系统内核fusion,采用了微内核架构,跟华为的鸿蒙有点类似。说不定哪天,Linux也可能被替换为fusion。

简单了解Google在Android外衣上的动作后,我们来看看瓤子的变化。应用层其实是每次Android新版本发布时主要的更新地。界面的设计风格、通知、安全隐私等,这些方面的变化也是用户比较容易直观感受到的。隐藏在可见界面下面的,是普通用户不可见的框架层。应用层跟框架层是骨肉相连的。框架层是骨,上层应用是肉。这两层的变化主要是通过SDK推送给用户的。使用新的SDK,应用就可以基于新的API开发APP了。当然,前提是设备也要支持新的API,这一点后面会介绍到。

计算机软件世界的一个显著特点是复制成本很低。所以,大部分人的工作都是在别人工作的基础上展开的。这一点在Android的库层体现的尤为明显。记得最开始接触Android系统开发时,看到了很多熟悉的开源库,这让我倍感亲切。包括无线的、网络的、音频的、视频的等等。如今,有不少已经被Google因为各种原因替换掉了。像Dalvik虚拟机变成ART了,基于Webkit的浏览器演变为基于chromium的浏览器。最初的音视频媒体框架被替换为更加高效的框架,新的渲染引擎也在引入进来。这些变化,不一定能够反映到API的变化上,这样应用开发者可能是无感的。但是,因为这些更新,用户体验的进化是一点一点在累积的。

对于库层的变化,除了原生程序开发人员和系统底层适配开发者外,其他开发者是很难接触到的。这两类关联人员,需要依赖NDK来进行相关开发工作。这是跟上层的SDK对应的。

对于硬件抽象层和内核层,因为嵌的更深,我们就不再介绍了。

其次,Android作为一个自成体系的闭环,有自己的生态系统。这可以从下面几个方面来了解:硬件、内核软件、库软件、Java运行时、框架软件、应用软件及模型、SDK、NDK、开发工具、开发语言、IDE、模拟器、辅助工具、应用商店等。下面我们分别介绍一下。

硬件不用说了,看得见、摸得着,我们最先接触到的部分。

Android开发不像PC开发,不是每一个人都有实际的硬件。特别是Android发展早期,硬件产品还不是很充足的时候。现在,这种情况好多了。但是,即便有实际的硬件,Android作为嵌入式领域产品,受终端的类型、系统的版本、硬件的裁剪等因素影响,应用开发人员不一定有完全匹配的硬件可用。这个时候,模拟器就发挥了先锋的作用。我们可以先在模拟器上调试软件。这里,模拟器跟实际硬件是对应的。Google提供了x86和ARM版本的系统镜像,运行在模拟器中,完成系统环境的模拟。

有了硬件环境,下一步就是操作系统。目前,Android产品主要还是基于Linux内核。不过,前面已有所述,Google对Linux内核做了一些修改适配,以适应安卓产品开发。这一部分,Google为了照顾硬件厂商,将部分驱动单独从内核中提出来,放到应用层,以规避内核开源的许可证要求。由于此,内核基金会和Google闹的不愉快。

库软件是应用层的基础。我们可以将标准C、C++相关的库,各种功能库都划归到这一部分。从运行的角度来看,这些库是系统镜像的构成部分。从静态的角度来看,这些库是NDK的组成部分。编译时依赖静态部分,运行时依赖动态部分。

Java运行时,这是上层代码的运行环境。虽然名字改变了,但是我们还是可以将其理解为Java虚拟机一类的东西,只不过目前的优化措施做得比较好,很多地方接近原生指令的性能,亦或甚至就是采用原生指令来翻译的。

Java运行时和库软件之间有一个交互,这样,上层应用的Java代码和底层的C/C++支撑代码就结合起来了。

框架软件是基于Java代码构建的,主要提供两部分功能,一是完成对底层的封装支撑,使得二者可以相互调用;二是建立应用软件抽象模型的实现。应用软件所使用的各种方便的组件,就是在这里实现的。

应用软件及模型,这是应用开发者直接面对的,也是用户在硬件之外,可触摸的部分。为了方便应用软件的开发,系统设计时对应用的构成进行了抽象建模。目前我们看到Android 的activity、service、receiver等,都属于这种抽象级别。

上面了解了各个层次的东西之后,我们再看看,为了建立Android系统生态,围绕上述各个部分,还需要准备什么。

虚拟机和镜像是针对硬件层面的,前面已有所述。在开发中,我们更常见的叫法是模拟器。也就是模拟一个Android手机。为了构建底层原生库,我们需要NDK。NDK包括了很多东西,比如编译工具链,基础的标准库,一些API接口的实现,底层的调试工具等等。使用NDK,我们就可以编译出在Android硬件上可执行的原生程序和库来,并可以对这些代码进行一定程度的调试。

和NDK对应的,还有一个SDK。基于SDK,我们可以编写上层的应用。SDK包含了上层Java层依赖的组件接口及实现。对于SDK的提供形式,可能是jar包,也可能是源码。除此,SDK中也可能包括有例子代码,官方文档等。不过实际中,SDK包含的可能远远不止这些。像镜像、模拟器等,都可能打包到SDK中发布给用户。

为了构建开发生态,还需要外围的辅助东西,这包括我们前面提到的开发工具(比如,SDK更新工具),开发语言,IDE(集成开发环境,包括代码的编辑、编译、打包、下载、调试等)。到此,我们完成了应用开发的准备。有了应用,还需要发布出来,以便让别人下载安装,进而使用,这就需要应用商店了。最终,整个生态链就构建起来了。

回过头来看,应用开发者所做的工作,其实是整个生态系统中的一小部分。这就像一个立体的魔法拼图,Google、各类软硬件厂商以及开发者共同参与,在一套规则约束下,协作完成整个拼图的搭建。(图片来自网络)

 

从技术的角度来看,我们需要在脑海的潜意识中意识到,NDK和SDK所提供的支撑,在设备中也是存在一份的。我们依赖NDK编译底层原生库,这部分代码在运行时,其依赖的动态库,则由Android设备里的副本来提供;同样,我们依赖SDK编译上层应用,这部分代码运行时,其依赖的框架组件,同样由Android设备里的副本来提供。Android采用了类似底层的孵化机制(fork--->zygote),系统初始化时,从原始简单应用不断进化为具有框架支撑能力的复杂应用。这样,当用户应用启动时,就由这个具备NDK和SDK支撑能力的复杂应用作为基础来孵化,如此,产生的应用就可以使用NDK和SDK提供的接口了。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/179050.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基本二叉树

文章目录接口实现三种基本遍历方式获取节点个数获取叶子节点个数获取树的高度返回第K层节点个数返回x所在节点二叉树的销毁OJ二叉树知识点及选择题N0 N2 1由中序和前序(或后序)确定结构的方法有N个元素的完全二叉树的深度是 logN 1选择题:…

Linux常用命令——sftp命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) sftp 交互式的文件传输程序 补充说明 sftp命令是一款交互式的文件传输程序,命令的运行和使用方式与ftp命令相似,但是,sftp命令对传输的所有信息使用ssh加密,它还…

预处理【详解】

本期介绍🍖 主要介绍:#define如何定义宏,宏替换的规则,为什么宏定义时不要吝啬我们的括号,为什么宏的参数不能带有副作用,宏和函数的区别。还讲解了预处理符号#和##,#undef指令,众多…

Swift(4)

目录 Dictionary集合 组合赋值符号 区间运算符 字符串字面量里的特殊字符 操作字符 Dictionary集合 相当于java中的Map集合 函数与闭包 函数也可以内嵌 函数其实就是闭包的一种特殊形式:一段可以被随后调用的代码块。闭包中的代码可以访问其生效范围内的变量和…

SpringMVC的@RequestMapping注解

SpringMVC的RequestMapping注解RequestMapping注解的功能RequestMapping注解的位置RequestMapping注解的value属性RequestMapping注解的method属性RequestMapping注解的params属性RequestMapping注解的headers属性什么是headers属性RequestMapping注解的功能 从注解名称上我们…

二叉树23:验证二叉搜索树

主要是我自己刷题的一些记录过程。如果有错可以指出哦,大家一起进步。 转载代码随想录 原文链接: 代码随想录 leetcode链接:344. 反转字符串 题目: 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。…

26. 命名空间

前言:如果你接触过c/c/c#/java,那么对于python中的命名空间也是如此,只不过在些许地方存在细微差异,不过倒无伤大雅。 1. 定义 命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 python 字典来实现…

lamda表达式

lamda表达式可以看作是一个匿名函数。编译器在编译的时候,会将lamda表达式处理成一个仿函数类,类名是类名是不重复的随机名称(因为一个作用域中可能存在多个仿函数),返回该仿函数的对象。 lamda既然可以看作是一个匿名…

文件操作(C语言)

目录 1、为什么使用文件 2、什么是文件 程序文件 数据文件 文件名 3、文件的打开和关闭 文件指针 文件的打开和关闭 4、文件的顺序读写 文件读写介绍 文件读写函数 fputc(字符 输出/写 函数) fgetc(字符 输入/读 函数) fputs&…

VMware Workstation安装:与 Device/Credential Guard 不兼容

VMware Workstation安装:与 Device/Credential Guard 不兼容 1、快速解决 安装最新版VMware Workstation,例如我安装的是VMware Workstation Pro 17: 是的,解决报错的办法,就是安装/升级VMware Workstation版本。 参…

Aspose.PDF 23.1.0 for .NET Crack

Aspose.PDF for .NET可以在 .NET 程序中生成、屏蔽、编辑甚至将 PDF 文件转换为多种格式,而无需依赖 Adob​​e Acrobat。它是.Net核心对PDF的创新处理,可以在跨平台软件中执行文档操作甚至任务管理。借助 API,用户可以创建、更改、呈现、保护…

Spring Cloud:网关Gateway

✨ Spring Cloud:网关Gateway微服务网关概述为什么需要微服务网关服务网关的介绍Getway基本介绍微服务架构中网关所处位置三大核心概念工作流程入门案例搭建新建模块**cloud-gateway-gateway9527**导入依赖application.yml主启动类实现动态路由测试Predicate 断言基本介绍Route…

详解信奥一本通1290:采药

1290:采药【题目描述】辰辰是个很有潜能、天资聪颖的孩子,他的梦想是称为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到个到处都是草药的山洞里对他说&#xff1…

Fisco Bcos区块链三(webase中间件平台一键部署)

文章目录区块链开荒技术文档:https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/index.html4. Webase一键部署Java环境变量配置MySQL安装Ubuntu安装mysql数据库安装后设置密码:Python部署PyMySQL部署(Python3.6)拉取…

SpringBoot-过滤器的使用(在访问页面时过滤掉未登录的用户使其不能访问相应页面)

目录 概述 前端编写 页面展示 后端编写 编写接口 过滤器的编写 过滤器功能实验 概述 解决需求:在用户未登录的情况下访问未登录不可访问的页面时,请求将被过滤到,将用户退回登录页面。 技术选型 前端:Vue ElementUI 后端…

MySQL事务的四大特性以及并发事务问题

事务的四大特性ACID 【原子性(Atomicity)】:事务是不可分割的最小单元,要么全部成功,要么全部失败。(eg:转账案例,转账过程中任何一步操作失败了,那么整个事务就失败了&a…

Python装饰器使用方法详解

文章目录1 装饰器背景知识1.1 基本概念1.2 应用场景2 简单的装饰器代码3 使用装饰器记录函数执行次数4 带参数的装饰器5 装饰器处理有返回值的函数1 装饰器背景知识 1.1 基本概念 装饰器(Decorator)是 Python 中一种函数或类,用来修饰其他函…

RabbitMQ部署

RabbitMQ部署1.单机部署1.1.下载镜像1.2.安装MQ1.3访问管理端2.集群部署2.1.集群分类2.2.设置网络1.单机部署 我们在Centos7虚拟机中使用Docker来安装,如未安装dockr,请参考《Centos7安装Docker》 1.1.下载镜像 方式一:在线拉取 docker …

C语言linux线程库pthread的简单使用教程

POSIX线程(pthread)库 POSIX线程库是用于C/C的基于标准的线程API。它允许产生一个新的并发流程。它在多处理器或多核系统上最为有效,在这些系统中,可以将流程安排在另一个处理器上运行,从而通过并行或分布式处理提高速…

flask框架全解

文章目录简介wsgiref安装配置文件方式一(debug方式配置)方式二(环境变量方式,很少见)方式三(配置文件方式)其他配置方式flask app路由组成写法动态路由的过滤查询字符串传参json和form等数据反向…