Gradle快速构建(三)多渠道打包及隐藏自动签名

文章内容:配置不同打包环境下(包括run运行的debug打包模式)指定签名,配置本地jks_config文件,自动编译签名包


还记得当初刚撸android时,在一家小公司用的eclipse开发,遇到一个发布bug,自己在运行debug打包模式测试都没有遇到过,但是通过jks签名包出来就升级安装出问题了,着实蛋疼,可想,配置一个正确的开发和测试环境的重要性,当我们打测试包时,总不能一直给人家debug签名版,不然多个电脑一起编译便会出现签名冲突问题,所以在debug模式下配置自定义签名也非常重要。同时,我们既然叫自动签名,那么总不能自己手动输入密码吧,那么配置签名文件密文如何放置才安全呢,且看文章吧

一 配置多渠道打包

多渠道打包在前2年面试可是必问知识点,其实实现起来非常简单,都是基本操作,实在也想不通有什么好问的,不过涉及到深入的技术,包括埋点统计等等,这些还是非常考验架构搭建的,在大型项目中也是重中之重。通过gradle简单的配置多渠道分包打包,结合上面修改打包报名一起修改如下:

  • 多渠道打包有2个要点,一个是获取channelID,这个从你发布的应用市场或者打包平台获取,比如友盟,google play
  • 第二点是在本地AndroidManifest.xml的meta-data中存储渠道ID,gradle配置主要通过替代符和分别打包

AndroidManifest替代符

    <!-- 自用渠道号设置 -->
   <meta-data
      android:name="yumeng"
      android:value="${CHANNEL}"/> 

gradle配置

二 配置本地签名密文

gradle配置自动签名,通过明文写入gradle不太安全,网上看到很多是通过命令控制台输入,不过还是不太喜欢,有点懒,我觉得通过本地保存比较舒服,动态读取。

  1. 在gradle.properties中配置

     # 配置release签名信息保存地址
     AutoGradleDemo.propertiesPath= D:\\appkey\\AutoGradleDemo.properties
     
     # 配置debug签名配置,直接放在本地就行
     AutoGradleDemo.debugStorePath=./AutoGradleDemoDebug.jks
     AutoGradleDemo.debugStorePassword=123456
     AutoGradleDemo.debugKeyAlias=debugKey
     AutoGradleDemo.debugKeyPassword=123456
    
  2. 在moudle build.gradle配置

     android {
        	//...
     	//加载gradle.properties中存储的release配置文件路径
         if (project.hasProperty("AutoGradleDemo.propertiesPath")
                 && new File(project.property("AutoGradleDemo.propertiesPath")).exists()) {
     
             Properties props = new Properties()
     		//读取配置文件
             props.load(new FileInputStream(file(project.property("AutoGradleDemo.propertiesPath"))))
     
             println("AutoGradleDemo: propertiesPath :" + project.property("AutoGradleDemo.propertiesPath"))
     		//导入release配置信息
             signingConfigs {
                 release {
                     def storeFile_str = props['AutoGradleDemo.storeFile']
                     def keyAlias_str = props['AutoGradleDemo.keyAlias']
                     def keyPassword_str = props['AutoGradleDemo.keyPassword']
                     def storePassword_str = props['AutoGradleDemo.storePassword']
     
                     if (keyAlias_str != null && keyPassword_str != null && storePassword_str != null && storeFile_str != null) {
                         println("storeFile: " + storeFile_str)
                         println("keyAlias: " + keyAlias_str)
                         println("keyPassword:" + keyPassword_str)
                         println("storePassword:" + storePassword_str)
     
                         storeFile file(storeFile_str + ".jks")
                         storePassword storePassword_str
                         keyAlias keyAlias_str
                         keyPassword keyPassword_str
                         println(getPath() + "-" + getName() + " pull release-configs successed!")
                     } else {
                         println("error: " + getPath() + "-" + getName() + " no jks-configs! ")
                     }
                 }
    
     			//debug签名配置在mould下全局gradle.properties
                 debug {
                     storeFile file(project['AutoGradleDemo.debugStorePath'])
                     storePassword project['AutoGradleDemo.debugStorePassword']
                     keyAlias project['AutoGradleDemo.debugKeyAlias']
                     keyPassword project['AutoGradleDemo.debugKeyPassword']
                 }
             }
         } else {
             println("error: " + getPath() + "-" + getName() + " AutoGradleDemo.propertiesPath is not exists! ")
         }
     
     	//声明打包配置
         buildTypes {
             release {
                 signingConfig signingConfigs.release
             }
             debug {
                 signingConfig signingConfigs.debug
             }
         }
     }
    
  3. release签名文件和信息存储目录

    • 其中AutoGradleDemo.properties配置文件内容

        AutoGradleDemo.storeFile=D:\\appkey\\AutoGradleDemo
        AutoGradleDemo.keyAlias=auto_gradle
        AutoGradleDemo.keyPassword=654321
        AutoGradleDemo.storePassword=123456
      
    • 目录

  4. Gradle编译结果

三 每次打包版本号自增

通过检查每次release打包指令,去自增版本号,不过当然有更好的方法,通过获取git分支配置versionCode,versionName,这个只是给个参考,想要更详尽和高级的使用方法,参考我的《自动化构建总结篇》文章

/**
 * 从 AutoGradleDemo.properties中读取信息, 检查到release打包,版本号自增,并存入到文件
 * @param path
 * @return
 */
def configAutoCompileInfo(def path) {
    def configsInfoFile = file(path)
    if (!configsInfoFile.canRead()) {
        throw new Exception("Could not find version.properties!")
    }
    Properties props = new Properties()
    //读取配置文件
    props.load(new FileInputStream(configsInfoFile))

    println("AutoGradleDemo: propertiesPath :" + path)

    def versionCode = props['AutoGradleDemo.versionCode'].toInteger()
    def versioName = props['AutoGradleDemo.versioName'].toString()
    /*检查到跑release task时版本号叠加*/
    def runTasks = gradle.startParameter.taskNames
    if ('assembleRelease' in runTasks) {
        props['AutoGradleDemo.versionCode'] = (++versionCode).toString()
        props.store(configsInfoFile.newWriter(), null)
        println("AutoGradleDemo: release versionCode increase current=" + props['AutoGradleDemo.versionCode'])
    }
    return props
}


 //加载gradle.properties中存储的release配置文件路径
if (project.hasProperty("AutoGradleDemo.propertiesPath")
        && new File(project.property("AutoGradleDemo.propertiesPath")).exists()) {
    Properties props = configAutoCompileInfo(project.property("AutoGradleDemo.propertiesPath"))

    defaultConfig {
        applicationId "com.auto.gradle"
        minSdkVersion 18
        targetSdkVersion 28
        versionCode props['AutoGradleDemo.versionCode'].toInteger()
        versionName props['AutoGradleDemo.versionName']
        if (versionCode != 0 && props['AutoGradleDemo.versionName'] != null) {
            println("versionCode: " + versionCode);
            println("versionName: " + versionName);
        } else {
            throw new Exception("error:  versionCode pull failed!")
        }

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {

                cppFlags ""
            }
        }
    }

} else {
    throw new Exception("error: " + getPath() + "-" + getName() + " AutoGradleDemo.propertiesPath is not exists! ")
}

四 指定打包路径及包名

通过判断包名以及多渠道名称,动态生成包名

  • gradle.properties

      #定义输出路径
      AutoGradleDemo.outReleaseFile=./app/relaseApk
      AutoGradleDemo.outDebugFile=./app/debugApk
      
      #定义包名
      AppName.release=AutoGradleDemoRelease
      AppName.debug=AutoGradleDemoDebug
    
  • APP:build.gradle

      applicationVariants.all { variant ->
          variant.outputs.all {
              def fileName
              //打包类型
              def buildType = variant.buildType.name
              //渠道名称
              def channelName = variant.productFlavors[0].name
              //获取时间戳
              def currentTime = new Date().format("YYYY_MM_dd", TimeZone.getTimeZone("GMT+08:00"))
              //制定输出路径
              if (buildType == "release") {
                  variant.getPackageApplication().outputDirectory = new File(project['AutoGradleDemo.outReleaseFile'] + "/${currentTime}")
                  println "compile name:-----------------${variant.getPackageApplication().outputDirectory}"
                  fileName = project['AppName.release'] + "_${channelName}_v${defaultConfig.versionName}_${currentTime}_${buildType}.apk"
                  println "compile name:-----------------${fileName}"
                  outputFileName = fileName;
              }
          }
      }
    
  • 结果

一些问题

1. Gradle Console窗口找不到

在网上很多gradle学习文章都是讲输出在gradle console,其实就是在build中查看就行

2. 配置本地参数读取不正确的问题

这个问题主要会发生的win系统,在配置参数文件时,空格或者其他特殊符号都是会默认读进去的,因此这些都是要注意项。使用Linux系统的同学,只要通过文档打印换行后缀就能发现,要简单很多。

3. Generate sign apk点击没反应

参考文档

https://www.timroes.de/2013/09/22/handling-signing-configs-with-gradle/

猜你喜欢

转载自blog.csdn.net/sslinp/article/details/84894376