Android 持续集成实践(五)—— ABI 分包、特殊渠道编译需求

文章目录

前言

两年前的持续集成完成之后,一直用到了最近都没啥大的变更要做。直到国内应用市场开始推 32 位和 64 位架构分包。
刚好前一段时间我们的 app 因为名称的原因,在 vivo 商店需要改名称才能上架,这就难受了,每次发版除了自动打包其他渠道外,还要单独编译加固 vivo 渠道,刚好这次一并解决了。
这篇文章相当于是对第三篇文章的一个补充。
注意这篇文章是以我自己配置的持续集成为基础的,以下为系列文章回顾。

系列文章

Android 持续集成实践(一)——从0开始搭建 Gitlab 服务器

Android 持续集成实践(二)——配置 Docker + gitlab-runner 实现线上自动编译

Android 持续集成实践(三)——编写 .gitlab-ci.yml 实现自动化

Android 持续集成实践(四)——配置 WebHook 通知编译结果

Android 持续集成实践(五)—— ABI 分包、特殊渠道编译需求

正文开始

ABI 分包

实现目标

发布正式版时,分别自动编译+自动多渠道 armeabi-v7a(32位) 和 arm64-v8a(64位) 的 apk;
发布测试版 时,编译一个同时包含 armeabi-v7a 和 x86 so 库的 apk。

实践
  1. abi 分割

    abi 分割可以直接配置 gradle 的 splits 节点来实现,需求是 release 版才需要分包,所以还需要在 abi 分割时,判断是 release 还是 debug。
    release 时启用 abi 分割;debug 时禁用分割,并且使用原来的 ndk 过滤配置多个架构 so 库

    // main module's build.gradle
    android{
        ...
         // 架构分包配置,只有 release 版需要架构分包;debug版还走以前的 ndk 过滤配置
         splits {
             boolean isReleaseTask = gradle.startParameter.taskNames.any { it.contains("Release") }
             if (!isReleaseTask) {
                 // debug 使用 ndk 过滤方式(splits 执行时机太靠前了,ndk配置在 buildTypes 中不生效)
                 android.defaultConfig.ndk { abiFilters "armeabi-v7a", "x86" }
             }
             // release 才会启用 abi 分割
             abi {
                 enable isReleaseTask
                 reset()
                 include "armeabi-v7a", "arm64-v8a"
                 universalApk false
             }
         }
         ...
     }
    
    
  2. apk 文件名修改

    abi 分割后,需要把 abi 的配置体现在 apk 名字上边,持续集成的流程在编译完后,要拿到 apk 继续执行自动加固、自动多渠道的任务,所以我们需要一个已知的确定的文件名,方便后边的持续集成任务拿到 apk。

     // main module's build.gradle
     ...
     import com.android.build.OutputFile
     ...
     android{
        ...
         applicationVariants.all { variant ->
             variant.outputs.all { output ->
                 def abiName = output.getFilter(OutputFile.ABI)
                 if (abiName != null)
                     outputFileName = "${variant.buildType.name}_${defaultConfig.applicationId}_${defaultConfig.versionName}_${defaultConfig.versionCode}_${abiName}.apk"
                 else
                     outputFileName = "${variant.buildType.name}_${defaultConfig.applicationId}_${defaultConfig.versionName}_${defaultConfig.versionCode}.apk"
             }
         }
         ...
     }
    
  3. 修改自动加固的配置

    现在 release 打包完是两个 apk 了,所以后续的加固和多渠道任务也需要改为支持两个 apk

     //修改文件 360jiagu
    
     #!/usr/bin/env bash
     
     ################
     #360加固 配置文件 #
     ################
     
     ...
     
     # 32位apk路径
     APK_NAME_32=release_com.wln100.future_${CI_COMMIT_TAG}_${CI_PIPELINE_ID}_armeabi-v7a.apk
     APK_PATH_32=app/build/outputs/apk/release/${APK_NAME_32}   #需要加固的apk路径
     # 64位apk路径
     APK_NAME_64=release_com.wln100.future_${CI_COMMIT_TAG}_${CI_PIPELINE_ID}_arm64-v8a.apk
     APK_PATH_64=app/build/outputs/apk/release/${APK_NAME_64}   #需要加固的apk路径
     # 输出加固包路径
     DEST=app/build/outputs/apk/release/
     
     ...
     
     echo "------ running! ------"
     
     chmod +x ${JAVACMD}
     ${JAVACMD} -jar ${BASE} -version
     ${JAVACMD} -jar ${BASE} -login ${NAME} ${PASSWORD}
     ${JAVACMD} -jar ${BASE} -importsign ${KEYSTORE_PATH} ${KEY_PASSWORD} ${KEY_ALIAS} ${STORE_PASSWORD} # 配置签名信息
     ${JAVACMD} -jar ${BASE} -showsign
     ${JAVACMD} -jar ${BASE} -deletemulpkg # 清除已配置的渠道信息
     ${JAVACMD} -jar ${BASE} -importmulpkg ./channels.txt # 配置渠道信息
     ${JAVACMD} -jar ${BASE} -showmulpkg
     ${JAVACMD} -jar ${BASE} -showconfig
     echo "------ 开始加固 32 位 apk ------"
     ${JAVACMD} -jar ${BASE} -jiagu ${APK_PATH_32} ${DEST} -autosign -automulpkg
     echo "------ 开始加固 64 位 apk ------"
     ${JAVACMD} -jar ${BASE} -jiagu ${APK_PATH_64} ${DEST} -autosign -automulpkg
     
     echo "------ finished! ------"
     
    

以上,配置结束,使用打包正式版的标签验证一下结果:

Android 持续集成实践(五)—— ABI 分包、特殊渠道编译需求

特殊渠道编译需求

特别说明,特殊渠道编译需求与上边的 abi 分包,这俩是没有关联的,各自独立的。如果你的项目刚好要 abi 分包的同时还要自动输出特殊需求的渠道包,就需要你自己来融合了

实现目标

持续集成时,自动编译加固多渠道 apk,同时需要 vivo 渠道的 apk 更改应用名称

实践

自动多渠道是依托 360 加固的 sdk 实现的,现在要 vivo 渠道自动编译的时候更改 app 名称,那 vivo 这个渠道就不能走 360 加固的多渠道命令统一处理了。

不自动编译的话,如何打包 vivo 渠道的 apk?修改版本号和版本名与自动编译生成的版本号版本名一致;修改清单文件中渠道原数据为 vivo;修改资源文件中 app_name 为运营要求的名称;执行编译任务 gradlew assembleRelease 坐等编译完成。。。

这个手动的过程,不复杂但是很繁琐,必须搞进程序集成流程中实现自动化解放双手。

一开始实现的思路是直接使用 gradle 的产品变种配置节点 productFlavors 来配置一个 vivo 渠道,这样是可行的,但是不太完美,配置变种后,无论打包 release 还是 debug,指定变种后都会打包变种包,不指定的话会打包所有的变种包。但是我们需要的只是在 release 的时候,去打包 vivo 这个特殊渠道,其他情况根本不需要。
定义变种后的打包命令结构是[编译类型+产品变种],=,既然定义变种后, debug 编译类型也会同时支持变种的话,那何不直接定义一个新的编译类型,与默认的 release 和 debug 编译类型并列呢。

  1. 移除 vivo 渠道的配置

  2. 新建编译类型 releaseVivo

    //main module's build.gradle  
    ...
    android{
        ...
        buildTypes{
            ...
             create("releaseVivo") {
                 initWith(getByName("release")) //继承 release 编译类型的配置  
                 manifestPlaceholders["app_label"] = "@string/app_name_vivo" //修改 vivo 渠道的 app 名字
                 manifestPlaceholders["umeng_channel"] = "vivo" //设置 vivo 渠道标识字段
                 matchingFallbacks = ["release"]  //其他 module 没有定义这个编译类型,匹配不到时使用 release 编译类型
             }
             ...
        }
        ...
    }
    ...
    
    

    输入 gradle 命令 gradlew assembleReleaseVivo,等待编译完后,其可以看到 vivo 渠道的 apk 了

  3. 修改 .gitlab-ci.yml

    ...
    
    # 编译阶段
    # 利用标签打正式包,格式:“x.x.x”
     release:
       stage: build
       only:
           - /^[\d]+\.[\d]+\.[\d]+$/
       except:
           - branches
       script:
           - ./update-version-code
           - ./gradlew assembleRelease assembleReleaseVivo
       artifacts:
           paths:
               - app/build/outputs/apk/release/
               - app/build/outputs/apk/releaseVivo/
               - app/build/outputs/mapping/release/
       tags:
           - android
     
    
    #region 加固和打渠道包阶段
    
     reinforceAndChannel:
       stage: reinforceAndChannel
       only:
         - /^[\d]+\.[\d]+\.[\d]+$/
       script:
         - ./360jiagu
       artifacts:
         paths:
           - app/build/outputs/apk/release/
           - app/build/outputs/apk/releaseVivo/
           - app/build/outputs/mapping/release/
       tags:
         - android
    
     #endregion
     
     ...
    
    
  4. 修改加固命令,支持同时加固 releaseVivo 编译出的 apk

    
     #!/usr/bin/env bash
    
     ################
     #360加固 配置文件 #
     ################
     
     ...
     
     APK_NAME=release_com.wln100.future_${CI_COMMIT_TAG}_${CI_PIPELINE_ID}.apk
     APK_PATH=app/build/outputs/apk/release/${APK_NAME}   #需要加固的apk路径
     DEST=app/build/outputs/apk/release/  #输出加固包路径
     
     # vivo 安装包加固路径配置
     VIVO_APK_NAME=releaseVivo_com.wln100.future_${CI_COMMIT_TAG}_${CI_PIPELINE_ID}.apk
     VIVO_APK_PATH=app/build/outputs/apk/releaseVivo/${VIVO_APK_NAME}   #需要加固的apk路径
     VIVO_DEST=app/build/outputs/apk/releaseVivo/  #输出加固包路径
     
     ...
     
     echo "------ running! ------"
     
     chmod +x ${JAVACMD}
     ${JAVACMD} -jar ${BASE} -version
     ${JAVACMD} -jar ${BASE} -login ${NAME} ${PASSWORD}
     ${JAVACMD} -jar ${BASE} -importsign ${KEYSTORE_PATH} ${KEY_PASSWORD} ${KEY_ALIAS} ${STORE_PASSWORD} # 配置签名信息
     ${JAVACMD} -jar ${BASE} -showsign
     ${JAVACMD} -jar ${BASE} -deletemulpkg # 清除已配置的渠道信息
     ${JAVACMD} -jar ${BASE} -importmulpkg ./channels.txt # 配置渠道信息
     ${JAVACMD} -jar ${BASE} -showmulpkg
     ${JAVACMD} -jar ${BASE} -showconfig
     ${JAVACMD} -jar ${BASE} -jiagu ${APK_PATH} ${DEST} -autosign -automulpkg
     
     echo "------ 开始加固 vivo 渠道 apk ------"
     ${JAVACMD} -jar ${BASE} -deletemulpkg # 清除已配置的渠道信息
     ${JAVACMD} -jar ${BASE} -showconfig
     ${JAVACMD} -jar ${BASE} -jiagu ${VIVO_APK_PATH} ${VIVO_DEST} -autosign
     
     echo "------ finished! ------"
     
    

以上,配置结束,使用打包正式版的标签验证一下结果:

Android 持续集成实践(五)—— ABI 分包、特殊渠道编译需求

Q&A

看的一头雾水?代码不完整?

再回顾一下持续集成系列文章,代码都有贴完整的,重复的就不在这篇里边加了

gradle 编译遇到 OOM?

同时异步走两个编译任务,需要的内存更大了,增加 jvm 内存配置吧

# 在 project 的 gradle.properties 中修改配置  
...
# 我的设置是,初始 2g,最大 4g  
org.gradle.jvmargs=-Xms2048M -Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
...

gitlab 线上 ci 报错:ERROR: Uploading artifacts to coordinator… too large archive

架构分割后,输出的 apk 成倍增长了,原来是一个 apk 打 6 个渠道包,总共 7 个 apk,现在 32 位和 64 位都要分别多渠道,有 14 个 apk,最后输出的 文件大小可想而知。我设置的 gitlab 输出文件大小最大是 300m,需要再加大点:

Android 持续集成实践(五)—— ABI 分包、特殊渠道编译需求

一些想法

最近 aab(Android App Bundle) 也在逐渐升温,墙外的 google 商店已经要求强制支持了。墙内的各商店,好像只是华为支持 aab 格式上传 app,再说到持续集成,以后可能还要实践 release 编译时输出 aab 格式文件,debug 编译时输出 apk 文件;国内加固工具对 aab 文件的加固支持情况具体怎么样还没研究(或者说 aab 文件其实已经不需要加固了?)

上一篇:国产化替代潮已至,亿信ABI一键转化Cognos BI,节省大量人力物力


下一篇:_GLIBCXX_USE_CXX11_ABI宏的作用