多渠道打包方案,其实很有玄机

640?wx_fmt=jpeg


/   今日科技快讯   /


近日华为乌克兰分公司发表公报说,公司已经中标乌克兰首都基辅地铁4G网络建设项目。华为中标的项目是其在中东欧和斯堪的纳维亚地区最大的地铁通信项目。


/   作者简介   /


大家周一好,新的一周继续努力吧!


本篇文章来自C1☆的投稿,分享了作者对Android中的打包方案的一些独特见解,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。


C1☆的博客地址:

https://cc1over.github.io/


/   前言   /


本来暑假应该是很忙很忙的时间,996的时间安排日子,但是没想到我们竟然出乎意料的闲,等着UI出图做项目,所以最近在闲暇时间之余写个apk系列的文章记录下项目里面临的问题以及整个调研思考的过程。


/   业务情况   /


我们的项目里面有个典型的业务就是多渠道打包,但是这种多渠道打包和传统意义上的多渠道打包有点不一致,我们项目里的多渠道打包,是要根据不同的渠道,有不同的apk名称,app名称,app的logo,以及多个键值对的渠道信息,而且打的包在40-50个左右,而且还在不断地增长中。


项目中原来使用的多渠道打包方案是Android官方提供的多渠道打包方案productFlavors,这种方式在使用的时候其实也并不是那么舒服,因为接近50个渠道信息,包括app名称,logo,3-5个与渠道相关的键值对信息,完全写在gradle里其实很难受,要定义好对应的sourceSet,以及map kv对应的数据,这样让gradle很臃肿,即便抽出一个独立的gradle apply进去,假如只是要打其中部分渠道的包又会相对比较麻烦。


最终在1.0版本是采取了xml配置文件的方式进行渠道信息的接入。


 
 


以这种xml的方式配置渠道信息,在打部分渠道包的时候把xml的其他不需要打包的渠道注释好就行了,这样其实灵活性不低,但是如果是刚接手项目的小伙伴刚拉下来,build的时候就会慢的飞起,而且这个文件也git管理起来了,这样就导致git管理上挺麻烦的。


而且productFlavors这种方式终归还是慢,实际测试过打50个我们项目的apk需要40-50min时间,然后发版的网站也没有批量发版的操作,只能一个渠道一个渠道的上传,麻烦的先不说,很容易就把渠道传错,然后就折腾个一番。


/   思考及探索   /


由于在项目中遇到的坑太多,所以笔者才决定去找一套新的方案去解决上述的问题。


当下流行的多渠道打包方案


productFlavors:不予考虑。


apktool:apktool是Android的一个逆向分析工具,原理其实就是把apk解开,添加渠道信息之后,重新打包成新的apk,具体步骤如下:


  • 复制一份新的apk

  • 通过apktool 工具,解压apk

  • 删除已有签名信息

  • 添加渠道信息

  • 通过apktool,重新打包生成新apk

  • 重新签名


方案点评:这种方案的多渠道打包是切实可行的,但是一开始笔者忽略了这种方案主要是因为网上资料不多,评价也不咋地。


Walle及VasDolly:美团多渠道打包方案和腾讯的多渠道打包方案其实在V1签名的处理上有所差异,Walle是添加空文件,VasDolly是添加zipcomment,v2签名就就往signing block里添加id-value的数据。


方案点评:这个方案其实当时真的很想很想用在项目里,但是不管是walle还是vaslloy针对的情况都是无需重签名添加渠道信息的,和业务需求格格不入。


得到启发


当时其实是在apk知识这一块受到了资源混淆框架AndResGuard的影响和启迪,当时资源混淆这一块的设计对我影响很大,当时就萌生了一种想法,AndResGuard混淆的原理其实也是通过修改读取arsc资源表的内容加以操作,其实就让笔者回顾当时看到apktool的做法。


因为便萌生了apktool多渠道打包,并封装成gradle-plugin的过程。


/   技术落地与困难   /


基于上面的探索和原理,梳理一遍整个多渠道打包的流程。


  • apktool解压apk

  • 读取manifest中信息,重点是读取application标签中的icon,roundIcon,label,并保存起来,由于manifest已经经过了编译,所以其实这个icon,roundIcon,label都是对应的resource.arsc文件的资源id

  • 读取resource.arsc文件的内容,修改label对应id的app名称,保存icon,roundIcon的资源id对应res目录下的资源

  • 修改上一步记录的res中的资源文件

  • 写回arsc文件,写回arsc文件和修改res资源文件的两个操作并发执行

  • 7zip压缩

  • 重签名


技术落地的过程其实借鉴了微信和美团的设计,其实整个arsc的读取操作都是根据apktool提供的jar包实现的,而我自己便在此之上添加写回的操作,笔者认为整个多渠道打包工具的难点在于resource.arsc文件的读取,修改以及写回操作。


困难1:resource.arsc读取


读取resource.arsc资源索引表的时候,会出现读多的异常。


问题原因:其实出现这个问题的原因就是因为笔者在书写读取操作的时候,其实并不想把太多东西保存在内存,而只是想把笔者想要的资源保存起来,所以其实并没有采取apktool中的读取流程,所以在读到最后一个TypeSpec中的Type的时候发现他会读多了。


解决方案:这个问题的解决方案有很多:


  • 直接catch EOF这个异常,因为如果遇到EOF异常就说明肯定读完,但是这样做的话,要把读过的数据保存在内存中,其实对于内存相对较低的情况不太友好

  • 还原apktool的做法

  • 自实现一种机制去检测读取的位置


困难2:修改resource.arsc中的字符串


这里字符串的编码格式踩了坑,由于没注意编码格式导致了出现乱码的状况,最后分别对StringBlock中的utf-8和utf-16编码进行适配与转换。解决代码如下:


 
 


重新写入工作的繁琐,由于是一个字节一个字节,其实容错率并不高,解决代码如下:


 
 


困难3:4的倍数


当时经过漫长的代码书写以及测试后发现,apk中的resource.arsc修改成功了,重签名也成功,用apktool解析也没有问题,但是就是安装不了。


当时解决这个问题,最初的想法其实是看PMS安装的源码和launcher显示图标的源码,分析写入操作到底是哪里出错。


然后读完了源码发现没有找到我要的答案,本想去读AssetManager读取资源的源码,但是,这个时候我在AndResGuard中再次得到了启发。在AndResGuard中有一段很关键的源码:



这段源码给了我问题的答案啊,其实不是写入有问题,只是没有把StringBlock中的字符串数目保持在4的倍数,导致安装失败。


解决方案:修改完resource.arsc文件的app label后判断一下长度,不是4的倍数便补0对齐。


/   小结   /


笔者在项目中遇到的困难不止于此,只列举了3个耗时最长的案例。


未来期望


虽然实现了功能,外部调用也是采用gradle的方式,但是对于内部的设计笔者还是不太满意,想通过进一步学习walle和vaslloy的源码加以改造原来的设计。


整个打包方案其实最耗时的是签名操作,所以笔者想添加上dex加壳,并尝试把壳dex中的注释信息删掉,尝试做到加固以及apk瘦身。


关于AndResGuard:其实真的从这个框架得到不少启发,甚是感谢,但是没有办法把这个框架导入到项目中,挺可惜的,因为项目推广的人员一直想在项目里添加换肤功能,如果把AndResGuard添加上去会比较蛋疼。


推荐阅读:

7张图带你轻松理解Java 线程安全

好奇一键登录是怎么实现的吗?进来了解一下?

由Android官方团队带你学习布局编辑器


欢迎关注我的公众号

学习技术或投稿


640.png?


640?wx_fmt=jpeg

长按上图,识别图中二维码即可关注


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值