前言

最近项目集成了Tinker,开始认为集成会比较简单,但是在实际操作的过程中还是遇到了一些问题,本文就会介绍在集成过程大家基本会遇到的主要问题。

考虑一:后台的选取

目前后台功能可以通过三种方式实现:

1、自己搭建后台布丁下发系统
2、第三方提供的服务,目前如原微信simsun大神的个人tinkerpatch平台,目前出于内测阶段,暂时免费。后期应该会按下发量对app进行收费。
3、腾讯Bugly提供的服务,提供了热更新的下发后台,集成到了bugly的升级sdk中。免费。
根据公司的精神,我们选择了Bugly作为我们的方案,这个大家都懂得。

考虑二:多渠道打包的问题

我们有将近100个渠道,每个渠道需要一个不同的渠道号,按product flavor的方式打出来的包的dex都有差异。这样就造成100个渠道包的热更新就需要100个补丁,这对管理简直是一个灾难。Tinker也对这种问题给出了推荐的方案,那就是使用开源项目packer-ng-plugin,它的原理是将渠道信息写在apk文件的zip comment中,这样在多渠道打包时就不会影响dex的内容。具体关于packer-ng-plugin的介绍,可以参考文档[Android打包工具packer-ng-plugin]。

考虑三:资源混淆所造成的问题

目前项目使用了资源混淆项目AndResGuard,关于AndResGuard的介绍,可以参考文档AndResGuard[Android混淆工具AndResGuard]。
也正是引入了资源混淆,热更新和多渠道打包都必须依赖资源混淆后生成的apk包才行。所以我们对编译流程进行了整合。

**整合前**

编译:编译直接使用AndResGuard提供的命令resguardRelease生成即可。resguardRelease生成的apk文件是没有资源混淆的。

./gradlew resguardRelease

Tinker生成补丁:直接调用tinkerPatchRelease任务生成的Release文件没有进行资源混淆

./gradlew tinkerPatchRelease

多渠道打包:使用packer-ng的命令apkRelease生成多渠道文件没有进行资源混淆

./gradlew apkRelease

**整合后**

主要解决两个问题:

1、Tinker生成补丁的原始和新的apk,需要使用资源混淆后的apk
2、多渠道打包所使用的原始apk,需要使用资源混淆后的apk

针对问题1:

当使用resguardRelease进行编译,在编译完成后,将生成的apk文件、R文件、map文件和resouce map文件拷贝到${buildDir}/bakApk/resguard目录下;

当使用tinkerPatchRelease生成补丁时,在tinkerPatchRelease任务前加入resguardTask
任务,这样生成补丁时使用的新旧apk都是资源混淆过的。核心的gradle代码如下:

 android.applicationVariants.all { variant ->
 /**
 * task type, you want to bak
 */
 def taskName = variant.name

 tasks.all {
 if (variant.buildType.name == 'release') {

 if ("tinkerPatch${taskName.capitalize()}".equalsIgnoreCase(it.name)) {

 // find resguard task
 def resguardTask
 tasks.all {
 if (it.name.startsWith("resguard")) {
 resguardTask = it
 }
 }
 it.doFirst({
 // change build apk path
 it.buildApkPath = "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/${project.getName()}-${taskName}_signed.apk"
 })

 // change task dependence to resguard task
 it.dependsOn resguardTask
 }

 if ("resguard${taskName.capitalize()}".equalsIgnoreCase(it.name)) {
 it.doLast {
 copy {
 def date = new Date().format("MMdd-HH-mm-ss")
 from "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/${project.getName()}-${taskName}_signed_7zip_aligned.apk"
 into file(bakPath.absolutePath + "/resguard")
 rename { String fileName ->
 fileName.replace("${project.getName()}-${taskName}_signed_7zip_aligned.apk", "${project.getName()}-${taskName}-${date}.apk")
 }

 from "${buildDir}/outputs/mapping/${taskName}/mapping.txt"
 into file(bakPath.absolutePath + "/resguard")
 rename { String fileName ->
 fileName.replace("mapping.txt", "${project.getName()}-${taskName}-${date}-mapping.txt")
 }

 from "${buildDir}/intermediates/symbols/${taskName}/R.txt"
 into file(bakPath.absolutePath + "/resguard")
 rename { String fileName ->
 fileName.replace("R.txt", "${project.getName()}-${taskName}-${date}-R.txt")
 }
 from "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/resource_mapping_${project.getName()}-release.txt"
 into file(bakPath.absolutePath + "/resguard")
 rename { String fileName ->
 fileName.replace("resource_mapping_${project.getName()}-release.txt", "${project.getName()}-${taskName}-${date}-resource_mapping.txt")
 }
 }
 }
 }
 }
 }

针对问题2、在AS中使用apkRelease任务打包的方式不再适用,可直接使用packer-ng所提供的命令行方式进行生成渠道包,经过测试,100个渠道包的确在10s左右就能打完,速度相当之快。考虑到市场推广人员会打不同渠道包,后期可做一个简易工具提供给市场推广人员。

整合后操作:

编译:

./gradlew resguardRelease

生成的apk文件放在${app}\build\bakApk\resguard\目录下

打补丁包:

./gradlew tinkerPatchRelease
./gradlew generateManifestForReleaseTinkerPatch

最终生成的补丁放在${app}\build\outputs\patch\目录下

多渠道打包:
针对编译后生成的包,使用packer-ng提供的命令行操作即可

java -jar PackerNg-x.x.x.jar apkFile marketFile outputDir

over~~

更多Tinker源码解析的文章请参考:

随机推荐

  1. springmvc和struts2的区别

    springmvc和struts2的区别 1.springmvc基于方法开发的,struts2基于类开发的. 2.单例和多例的区别:springmvc在映射的时候,通过形参来接收参数的,是将url和c ...

  2. MOB 短信验证

    工具/原料   Android Studio mob SDK中的jar 和.so文件 方法/步骤   1 把3个jar 放入libs   并添加依赖 在项目的build.gradle里面   在你的项 ...

  3. python之lxml(xpath)

    bs4确实没这个好用,bs4的树太复杂 lxml很好 定位非常好 详细解说在注释里面有了 #!/usr/bin/python3.4 # -*- coding: utf-8 -*- from lxml ...

  4. AndroidStudio学习记录

    AndroidStudio学习记录 1. 插件的使用. plugins.jetbrains.com插件网站. 2. 目录介绍: 1.Studio中有Project和Module的概念,前面说到Stud ...

  5. Android SDK离线安装

    Android SDK离线安装是本文要介绍的内容,主要是来了解并学习Android SDK安装的内容,具体关于Android SDK是如何离线安装的内容来看本文详解. Android开发环境,完整的说 ...

  6. iOS UIAlertView 文字对其方式 文字大小 设置方法

    - (void) willPresentAlertView:(UIAlertView *)alertView { for (UIView *subViewin alertView.subviews) ...

  7. ubuntu的应用程序哪里找

    一般来说11.04以前的桌面是gnome,点左上角的那个小圆圈,会出来一个下拉菜单,里面就有应用程序. 11.10以后的桌面换成unity 在dash中寻找应用程序很不方便,知道名字的还好,不知道名字 ...

  8. Linux下的MySQL5.7.14启动方法

    启动MySQL服务: systemctl start mysql 启动MySQL服务(安全方式): mysqld_safe --user=mysql & 登录MySQL(有密码): mysql ...

  9. [NOIP2002]字串变换 T2 双向BFS

    题目描述 已知有两个字串  A,B  及一组字串变换的规则(至多6个规则): A1−>B1 A2−>B2 规则的含义为:在  A$中的子串  A1可以变换为可以变换为B1.A2可以变换为可 ...

  10. .NET Core 必备安全措施

    .NET Core大大简化了.NET应用程序的开发.它的自动配置和启动依赖大大减少了开始一个应用所需的代码和配置量,本文目的是介绍如何创建更安全的.NET Core应用程序. 1.在生产中使用HTTP ...