享学课堂诚邀作者:周周
转载请声明出处!
正文大纲
1. gradle是什么2. groovy语言的特性以及它和java的关系3. 为什么你的apk打包这么慢4. 如何利用gradle编程解决工作中的实际问题5. gradle的高级用法(gradle多渠道快速打包插件)
5. gradle的高级用法(gradle多渠道快速打包插件)
本节小目录
productFlavors多渠道打包的优势与缺陷android中签名的那些梗如何在V1签名校验下写入渠道信息如何在V2/V3签名校验下写入渠道信息如何发布gradle插件到mavenLocal
productFlavors多渠道打包的优势与缺陷
上一篇文章详细讲了如何利用gradle官方的productFlavors去实现多风味打包,现在来分析一下这种方式的优缺点。
优势
毕竟是官方爸爸给的打包方案,优势之一那就是功能全面. 完全利用gradle编程框架内的函数来设置“风味”的特别参数,理论上可以通过配置产生造成任何你想看到的差异,
比如,applicationId 包名,versionCode 版本号,versionName 版本名,manifestPlaceHolder 清单文件预留字段,buildConfigField BuildConfig文件内的字段
等等. 至于其他的,我没有去一一尝试,但是应该八九不离十。
缺陷
"慢"
是的,比较慢,如果是大型项目,需要快速打出 2个维度,每个维度都是5x5的包,那么 编译器就会进行25次完整的apk打包流程。
啥?apk打包流程不知道?
![43571d321bec0a4a0a2c6c5a0cd2f9fc.png](https://i-blog.csdnimg.cn/blog_migrate/8823931d6d2fc694bc1515b8113cde90.jpeg)
上图解读:
一个apk,主要包含3个部分.java代码部分,包括第三方依赖包,包括aidl跨进程调用的代码,会统一变成一个或者多个dex文件。资源文件部分,通过aapt,生成一个res文件夹以及一个 resources.arsc 资源映射.apk签名,没有通过签名的apk文件,会在安装的时候校验失败,无法安装。签名之后,相对于签名之前,会多出一个和签名相关的META_INF目录。
无论是dex,资源映射,或是签名,都是比较耗费时间的,而productFlavors多风味打包,这3个过程都需要完整走N次,自然要耗费大量的时间。而事实上,我们并不是所有的包都有巨大的差异,很多都是在 defaultConfig的基础上,稍稍修改一些参数,比如,
buildConfigField "String", "APP_NAME", "AAAAAAAA"
那么,有没有办法,绕过这些完整打包流程,直接将 渠道参数注入到其他的地方(不再使用productFlavors,meta-data 这一套方案)?
还真有,本文将会详述。
但是有一点,如果我们想把渠道参数放到别的地方,那就必须要对apk进行了修改,这可能会造成 安装时的签名校验失败,一旦失败,无法安装,前功尽弃。
所以,在执行新的打包方案之前,必须先了解 android的签名那些梗.
android中签名的那些梗
android apk签名的原理详情不是本文重点,所以这里只是简单说一些结论。
- 签名的本质
保护. 是的,对一个apk进行签名,其实就是对apk中的文件进行保护的过程。Android系统 在安装apk的时候,会对 签名进行校验,如果发现文件被篡改,就会拒绝安装,以保护用户信息和系统安全。
- APK签名的类型
android的十多年历史上,签名一共就3种,V1,V2,V3。
V1 : 是最早出现的,它所保护的是 APK中的原本存在的文件。
何意?上面的apk打包流程解读的中写了,apk原本存在java文件最终转化成的dex,资源文件整合而成的src 目录和resources.arsc映射文件等,这些在签名之前原本就存在的文件,都会受到V1签名机制的保护,而生成一个一个类似 SHA1-Digest: OGGiGAP82euSpAMCew2iu3rdTeE= 的签名摘要:
![7d73ae0e95ee19bac1518752187cbdc8.png](https://i-blog.csdnimg.cn/blog_migrate/737c25de1175c24bdc94b76f276a17df.jpeg)
比如上图,如果清单文件,被人解压之后篡改,再打包成apk,安装的时候,签名校验就会失败,禁止安装。
![9e49af9888eac2c8447f0c4eba9923b8.png](https://i-blog.csdnimg.cn/blog_migrate/d01d202578eb6df17482e11d2367a7a0.jpeg)
上面的dex文件和res里面的资源文件也被保护.
但是,上面我著名了2个粗体字,原本!这就意味着,如果我在上图中META-INF这个签名之后生成的目录里面加点东西,是不会影响签名校验的,这里记一下小本本,后面要考,- -!
V2/V3 签名:
同样是保护apk,V2 V3保护的则不是签名之前原本存在的文件了,而是整个apk的字节数据。无论签名之前还是签名之后,只要apk中的文件发生了任何变化,字节数据就会有变,安装时就会签名校验失败,这相对于V1是更加严格的apk保护方案。Android 7.0系统将会优先使用V2签名,Android 9.0系统优先使用V3签名,V2 V3有区别,但是在本文中无需区分,两者可以分为一类去处理。优先?意思就是,如果同时存在V1,V2和V3签名,Android7.0以下的系统会直接使用V1签名,Android7.0以上,9.0以下的系统,将会进行V2签名的校验,而 9.0以上系统,将会使用V3签名进行校验。
如果只存在一个V1签名,任何系统都没得选,只能校验V1.
V2/V3的签名原理比较复杂,后面再详述。
如何在V1签名校验下写入渠道信息
依旧是STAR法则
Situation 情境
多渠道打包,在日常工作中,每个包之间的差别并没有那么大,不需要改动包名,版本号,等等app内核参数,而只需要 生成我们自定义的参数,比如 channelName 多渠道名,themeColor 多主体颜色设置.
Task 任务
由于每一个包之间的差别很小,而且不涉及到app的内核参数(包名,版本号),所以,再用productFlavors就比较大材小用了,而且由于数量上很多,productFlavors效率很低,所以不可取。我们的任务是,快速打出差别很小,数量很多的包.
Action 行动
我们将采取什么行动?重点来了!
V1签名那些梗,再回顾一下,V1签名对于apk的保护,是基于apk原本的文件,画图表示:
![b2cbab1426949f24f1867147a12b8722.png](https://i-blog.csdnimg.cn/blog_migrate/56b58526f9632e755f84efdfab746c5a.jpeg)
一个apk,在签名之前,就是这么一些东西。
但是,签名之后,就变成了:
![467f8ba844c0389017b066cb8ecff2be.png](https://i-blog.csdnimg.cn/blog_migrate/50eaf1334ae65fd6db54a500ab2d4a64.jpeg)
所以,确定思路,我们只需要1.在META-INF中加入自己的文件,只要是新增的文件,就不会导致签名失败,其他的文件不要去碰。2. 打包成功的 特殊"风味"apk,安装之后,我们要从刚才META-INF中新增的文件中读取出我们自己的"风味"信息
就能达成 V1签名插入风味信息的目的!
![4e2a8ec0d4b730669f5dd355e4d134c1.png](https://i-blog.csdnimg.cn/blog_migrate/867a76604360b9957ea831c868eba7c1.jpeg)
Github Demo地址
https://github.com/18598925736/GradleStudy1023(请进入master分支)
demo重难点解读
其实说到底,就是文件IO流操作,只不过这次针对的文件不是普通文件,而是压缩文件,因为apk文件本身就是一个压缩包。
看代码lib/FlavorUtil.java!
然而,app安装之后,需要解读风味参数:
![ad55017b018dfd77e580477e2ff1d80a.png](https://i-blog.csdnimg.cn/blog_migrate/80ca33b32ca43af45762868c4b9596c4.jpeg)
Demo中,我兼容了 productFlavor 的多维度打包的功能,
![8652e6973e3e919cad39f1e74eddf7d1.png](https://i-blog.csdnimg.cn/blog_migrate/023b03b0f2779c7c262eb95034d5eb1c.jpeg)
![fa2bebef49085b18e00c57f13721d40a.png](https://i-blog.csdnimg.cn/blog_migrate/f518b2c402dfb468fbe0a70234d875ce.jpeg)
![e9d310a577d09dcee1e8e0449c110734.png](https://i-blog.csdnimg.cn/blog_migrate/5e6adca2ad6acb10305075105fd7a9ce.jpeg)
Result 结果
命令行 操作:
- gradlew clean(遇事不决,先clean)
- gradlew assembleDebug (生成基准包)
- gradlew assembleChannelPkgs (生成风味包)
看一眼结果吧
基准包的生成 6S
![946f6dff864db209b74b2b2b4a0409c4.png](https://i-blog.csdnimg.cn/blog_migrate/2f71c8a3be482f66058b2577ffaa0c99.jpeg)
风味包的生成 4S
![ca52b94c64b66068fe39cde912cc2ed9.png](https://i-blog.csdnimg.cn/blog_migrate/90e8f47f3dff9b9d9e55d023befe2fc1.jpeg)
一共生成了4*4=16个风味包,效率很高,只花了4S.
来我们挑一个包来安装一下,就决定是你了,豌豆荚wdj 的灰色包 !:
![cb94c26fc5df38310df445321a049386.png](https://i-blog.csdnimg.cn/blog_migrate/a91328bb6410b92d978bb9e1ce60d4d5.jpeg)
![6e8408489dfb0352f841f0dfdf5b5601.png](https://i-blog.csdnimg.cn/blog_migrate/e9693c21a315f31e3562be3d7d66c84a.jpeg)
破费!
未完待续...
既然来了,点个关注再走呗~