搜游网:好玩的单机游戏下载站!
发布时间:2023-12-19 19:59:20来源:搜游网
现如今随着组件化, 插件化框架以及热修复,AOP编程等高级用法的新起,不得不驱使大家去了解更加底层的原理,上一篇文章笔者介绍了关于JVM字节码的理解,这篇文章笔者就来讲解下我们apk从编译到安装的过程。
首先来了解下我们apk的成员
apk的配置文件,内部包含了应用的名称,权限声明,四大组件等信息的声明,如果说app是一本书,它就是这本书的封面
由源码编译后的的.class文件经过进一步转换成Android系统可识别的Dalvik Byte Code,包括第三方jar或aar中的class文件
资源索引表,使用的是一个二进制流的格式,记录R文件id和资源文件路径的一个映射表以及我们在res文件夹下放入一个资源文件,aapt就会自动在R文件中生成对应的资源文件id,而R文件只能保证编译不报错,实际运行时还是需要依赖resources.arsc中的映射关系,通过R文件id找到实际资源文件路径。
存放未编译的资源文件
也是资源文件夹,和res的区别:res文件会在R文件中生成索引,运行时使用索引获取资源文件,而asserts目录下的文件不会在R文件中生成索引,使用AssetManager访问文件
存储so动态库
存储签名和校验信息,确保程序的完整性。Apk打包时会使用签名文件对apk进行签名校验,并将结果记录到META-INF 目录下,Apk安装的时候设备也会对应用进行一次校验,并和META-INF 目录下的校验信息对比,防止apk在出包后被篡改
放一张官方apk编译过程图:
旧版本打包编译过程更详细的描述了具体过程
到此我们已经了解另外apk的打包和编译的一个完整流程
这里我们提出两个问题
这两个问题其实答案都是相通的。
在前面一篇文章讲解class文件结构的时候,说到过,class文件有一个常量池的结构,其存储了当前class文件所需的所有常量字符串,外部访问常量的时候,是通过索引的方式进行访问
这里xml文件编译为resources.arsc过程也是这么一个方式。
那为什么要这么使用呢?
字符串复用,资源复用:当前xml文件的标签,属性名称以及属性值都会被编译到resources.arsc资源池中,且去除重复的字段,外部访问的时候,只需要访问使用当前资源索引就可以在资源池中找到对应的资源信息,且不需要每次都去解析对应的字符串,解析资源效率高。第二个问题在第一个问题解中就可以找到了
前面都是讲解源文件编译过程,这里我们再来突出下apk的签名校验过程
如MD5加密后的字符串就是一个消息摘要特点:可以保证数据完整性,但是无法保证数据安全性和不可篡改性
两部分组成:签名算法和验证算法
知识点:
公钥密码体制 对称加密算法和非对称加密算法
加密:通过公钥使用加密算法对明文进行加密,得到密文
解密:通过私钥使用解密算法对密文进行解密,得到明文
公钥加密的内容一定需要知道私钥才能解出明文由管理员生成一套公钥和私钥。公钥和算法是公开的,私钥是只有管理员才有,保证数据不可以篡改
RSA:
如果单独使用私钥进行加密只可以保证数据的完整性,无法保证数据的保密性且数据大时加密的效率速度很低,所以采用加密摘要算法生成的摘要消息弥补缺点
具体步骤:
发送者:
接收者:
签名过程:
签名三兄弟:1.MANIFEST.MF2.CERT.SF3.CERT.RSA
该内容保存的是逐一遍历 APK 中的所有条目,使用摘要算法如SHA1或者SHA256算出摘要信息,并使用base64编码后,存放到MANIFEST.MF块中每个块包含一个Name属性:存放该文件的路径
SHA1-Digest-Manifest:对整个 MANIFEST.MF 文件做 SHA1(或者 SHA256)后再用 Base64 编码
SHA1-Digest:对 MANIFEST.MF 的各个条目做 SHA1(或者 SHA256)后再用 Base64 编码
这里会把之前生成的 CERT.SF 文件,用私钥计算出签名, 然后将签名以及包含公钥信息的数字证书一同写入 CERT.RSA 中保存
这个数字证书就是我们android签名的时候使用的签名keystore文件:
使用下面命令查看签名证书情况:
penssl pkcs7 -inform DER -in /<文件存放路径>/Sample-release_new/original/META-INF/CERT.RSA -text -noout -print_certs
完整签名流程:
校验过程:在安装步骤校验:
1.检查APK中所有的文件,对应的摘要值和MANIFEST.MF中的值保持一致
2.对MANIFEST.MF中的值做二次摘要,查看是否和CERT.SF中的值保持一致
3.使用数字证书文件CERT.RSA检查SF文件有没被修改过,使用公钥证书解密
4.解密后的摘要信息和步骤2中的二次摘要信息对比,看下是否一致
5.一致就通过,说明apk信息没有被更改过
为什么使用这样的签名流程呢?
1.更改APK文件里面的文件,MANIFEST.MF中的摘要信息不一致,校验失败
2.在1的基础上更改MANIFEST.MF的摘要信息,那么和CERT.SF中的摘要信息会不一致,校验失败
3.在2的基础上更改CERT.SF中的摘要信息,那么CERT.RSA中的签名信息不一致,校验失败。
4.在3的基础上更改证书,不行,因为没有私钥。
所有可以基本上保证数据的不可篡改性
v1缺点:
v2签名:
就是把 APK 按照 1M 大小分割,分别计算这些分段的摘要,最后把这些分段的摘要在进行计算得到最终的摘要也就是 APK 的摘要。然后将 APK 的摘要 + 数字证书 + 其他属性生成签名数据写入到 APK Signing Block 区块。
v2校验:
v2 签名机制是在 Android 7.0 以及以上版本才支持。因此对于 Android 7.0 以及以上版本,在安装过程中,如果发现有 v2 签名块,则必须走 v2 签名机制,不能绕过。否则降级走 v1 签名机制。v1 和 v2 签名机制是可以同时存在的,其中对于 v1 和 v2 版本同时存在的时候,v1 版本的 META_INF 的 .SF 文件属性当中有一个 X-Android-APK-Signed 属性:X-Android-APK-Signed: 2
v2 对多渠道打包的影响
之前的渠道包生成方案是通过在 META-INF 目录下添加空文件,用空文件的名称来作为渠道的唯一标识。但在新的应用签名方案下 META-INF 已经被列入了保护区了,向 META-INF 添加空文件的方案会对区块 1、3、4 都会有影响。
总结V2:
CI 即 持续集成,在大型开发团队中,CI 的建设是重中之重,CI 主要包括 打包构建、Code Review、代码工程管理、代码扫描 等一系列流程。它的 整套运转体系 可以简化为下图:
构建 CI 的目的主要是为了解决以下四个问题。
随着业务的发展,基础组件库的数量会持续上涨,这个时候组件间的关系就会变得错综复杂,这将会导致如下 两个问题:
在日常的功能开发中,我们一般都会经 代码开发、组件发版、组件集成、打包、测试这五个步骤。如果测试发现 Bug 需要进行修复,然后会再次经历代码修改、组件发版、组件集成、打包、测试,直到测试通过交付产品。传统的研发流程如下图所示:
可以看到,开发同学在整个开发流程中需要手动提交 MR、升级组件、触发打包以及去实时监控流程的状态,这样肯定会严重影响开发的专注度,降低研发的生产力。
随着 App从 项目初期 => 成长期 => 成熟期,对性能的要求会越来越高,为了保障性能的足够稳定,我们需要制造出许多性能监控的工具,以实时监控我们应用的性能。而 App 性能监控体系必须和 CI 结合起来,以实现流程的自动化和平台化。
随着 App 的体积变大,依赖变多,项目的编译构建速度会越来越慢,缓慢的编译速度会严重拖垮开发同学的研发效率。因此,提升 App 的编译构建速度刻不容缓。
持续集成涉及的流程非常多,但是有 两个主要的步骤是非常重要 的,具体如下所示:
为了防止不符合规范的代码提交到远程仓库中,我们需要 自定义一套符合自身项目的编码规范,并使用专门的插件来检测。自定义代码检测可以通过完全自己实现或者扩展 Findbugs 插件,例如美团就利用 Findbugs 实现了 Android 漏洞扫描工具 Code Arbiter,其中 FindBugs 是一个静态分析工具,它一般用来检查类或者 JAR 文件,将字节码与一组缺陷模式进行对比来发现可能存在的问题,它可以以独立的 JAR 包形式运行,也可以作为集成开发工具的插件形式而存在。而 FindBugs 插件具有着极强的可扩展性,只需要将扩展的 JAR 包导入 FindBugs 插件,重启 AS,即可完成相关功能的扩展。
在 FindBugs 有一款专门对安全问题进行检测的扩展插件 Find Security Bugs,该插件主要用于对 Web 安全问题进行检测,也有极少对Android相关安全问题的检测规则。我们只需要 定制化自己的 Find Security Bugs,通过增加检测项来检测尽可能多的安全问题,通过优化检测规则来减少检测的误报 即可,这里我们可以直接使用 Android_Code_Arbiter 这个插件,它 去除了其中跟 Android 漏洞无关的漏洞,保留了与 Android 相关的,并增加了其它的一些检测项,以此形成了针对与于 Android 的源码审计工具。
此外,我们也可以使用 第三方的代码检查工具,例如收费的 Coverity,以及 Facebook 开源的 Infer。
然而,尽管将问题代码扫描出来了,可是还是会有不少开发同学不知道如何修改,对于这种情况,我们可以给在自定义代码扫描工具的时候,对于每一个问题检查项都给出对应的修改方针。
最后,我们可以据此建立一个解决项目异常的流程:建立一个服务专门每天跑项目的 Lint 检查,跑完将警告汇总分配到对应的负责人身上,并邮件告知他,直到上线。
Code Review 非常重要,在每一次提交代码时,我们都需要自己进行一次 Code Review,然后再让别人去 Review,以建立自身良好的技术品牌。
有些同学可能会认为 CI 并不重要,它好像跟具体的技术并无关联。但是,我们需要知道,学会不仅仅是钻在开发角度看问题,跳脱出来,站在用户角度,站在产品角度,或许会有意外的收获。
在本篇文章,我们即涉及到了 Android 编译的深度方面:App 的编译和打包流程、签名算法的原理,也涉及到了 Android 编译的广度方面:持续集成。因此,在我们学习的过程中,技术就像是一棵树,在顶部叶子上各个领域看似毫不相干,但是在一个领域越往下深入,各个领域相互交错到的知识或者设计方式就越多,所以技术深度和广度并不是对立面,对技术深度的探索不仅有利于你在特定领域有更深理解,更加可以帮助你轻松切换到另一个领域,特别是像前端的各细分领域的工作,很多领域的知识背后都殊途同归,而技术的广度也不是有的人说的那样不堪,在有技术深度的基础上,去拓展自己的技术广度,其实会让你对原有技术的理解变得更加地深入。
上一篇:返回列表
王牌战士幽灵怎么玩
第五人格游戏先知天赋怎么加点-第五人格先知怎么玩
王牌战士风魔刺客团队歼灭攻略
跑跑卡丁车手游制霸赛场任务攻略
王者荣耀王者模拟战攻略-王者模拟战最强阵容玩法介绍
崩坏3精英工坊武器更新
王牌战士据点占领怎么玩-王牌战士据点占领用什么英雄
古今江湖童姥牌组厉害吗
崩坏3熔岩旅馆怎么通关
方舟手游辅助器
其它游戏
植物大战僵尸2恐龙危机内购破解版
其它游戏
7344游戏盒
角色扮演
gta6手机版
动作格斗
坠星大陆手游
动作格斗
梦三国
角色扮演
最强音响师
角色扮演
最后的黄昏
角色扮演
魔道天师
角色扮演