如何使用Gradle脚本在Android Studio中自动增加和释放已签名的apk

时间:2015-07-07 09:46:27

标签: android android-studio gradle apk

我正在尝试自动更新Android Manifest中的versionName和VersionCode参数,并在输出文件名中使用它们而不是“app-release.apk”。

this site我在build.gradle文件中添加了这段代码:

import java.util.regex.Pattern
import com.android.builder.core.DefaultManifestParser

def mVersionCode
def mNextVersionName
def newName

task ('increaseVersionCode') << {
    def manifestFile = file("src/main/AndroidManifest.xml")
    def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
    def manifestText = manifestFile.getText()
    def matcher = pattern.matcher(manifestText)
    matcher.find()
    mVersionCode = Integer.parseInt(matcher.group(1))
    def manifestContent = matcher.replaceAll("versionCode=\"" + ++mVersionCode + "\"")
    manifestFile.write(manifestContent)

}

task ('incrementVersionName') << {
    def manifestFile = file("src/main/AndroidManifest.xml")
    def patternVersionNumber = Pattern.compile("versionName=\"(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\"")
    def manifestText = manifestFile.getText()
    def matcherVersionNumber = patternVersionNumber.matcher(manifestText)
    matcherVersionNumber.find()
    def majorVersion = Integer.parseInt(matcherVersionNumber.group(1))
    def minorVersion = Integer.parseInt(matcherVersionNumber.group(2))
    def pointVersion = Integer.parseInt(matcherVersionNumber.group(3))
    def buildVersion = Integer.parseInt(matcherVersionNumber.group(4))
    mNextVersionName = majorVersion + "." + minorVersion + "." + pointVersion + "." + (buildVersion + 1)
    def manifestContent = matcherVersionNumber.replaceAll("versionName=\"" + mNextVersionName + "\"")
    manifestFile.write(manifestContent)

}

tasks.whenTaskAdded { task ->
    if (task.name == 'generateReleaseBuildConfig') {
        task.dependsOn 'increaseVersionCode'
        task.dependsOn 'incrementVersionName'
    }
}

此代码完美运行,2个任务运行并正确更新清单文件。 现在我想在mVersionCode内的mNextVersionName块中使用2个变量releasebuildTypes,如下所示:

newName = defaultConfig.applicationId + "-" + mNextVersionName + " (" + mVersionCode + ").apk"
applicationVariants.all { variant ->
                variant.outputs.each {output ->
                    def file = output.outputFile
                    output.outputFile = new File(file.parent, file.name.replace("app-release.apk", newName))
                }
            }

但是2的返回值为null。

我还尝试设置属性和额外属性:

task.setProperty("vName", mNextVersionName) 
ext.vName = mNextVersionName 
extensions.extraProperties.set("vName", mNextVersionName)

在2个任务中,没有运气就将它们放在release区块中。

有人对如何做到这一点有想法吗?

3 个答案:

答案 0 :(得分:2)

没有人回答,但我找到了一个工作解决方案。我不喜欢它,它可以更好的方式完成,但现在是我发现的唯一解决方法。

我仍然在寻找更好的解决方案,如果你有一个,我会乐意阅读并使用它而不是我的。

所以,我在gradle.build文件中添加了一个新任务,它只是复制了一个app-release.apk&#39;使用清单文件中的值对文件进行重命名:

task copia{
    dependsOn('assembleRelease')
    def manifestFile = file("src/main/AndroidManifest.xml")
    def patternVersionNumber = Pattern.compile("versionName=\"(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\"")
    def manifestText = manifestFile.getText()
    def matcherVersionNumber = patternVersionNumber.matcher(manifestText)
    matcherVersionNumber.find()
    def majorVersion = Integer.parseInt(matcherVersionNumber.group(1))
    def minorVersion = Integer.parseInt(matcherVersionNumber.group(2))
    def pointVersion = Integer.parseInt(matcherVersionNumber.group(3))
    def buildVersion = Integer.parseInt(matcherVersionNumber.group(4))
    def mVersionName = majorVersion + "." + minorVersion + "." + pointVersion + "." + (buildVersion)

    def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
    def matcher = pattern.matcher(manifestText)
    matcher.find()
    def myVersionCode = Integer.parseInt(matcher.group(1))
    copy {
        from 'app-release.apk'
        rename { String fileName ->
            fileName.replace('app-release.apk', 'com.walker93.catpadova-' + mVersionName + ' (' + myVersionCode + ').apk')
        }
        into 'apk_outputs'
    }
}

正如您所看到的,它只是前面2个任务中代码的复制和编辑版本,带有copy {}函数(此处为docs),它读取versionName和versionCode没有递增它们的值,然后它将它们放在新文件名中我将要替换。

此任务仍然需要另外两个任务,所以最后你将有3个任务。 在此任务的第一行中有dependsOn(assembleRelease)。这非常重要,它将运行生成更新和签名的apk的所有其他默认发布构建任务(包括我们在清单中递增和写入的2个任务)。

现在,如果您尝试运行&#34;生成已签名的APK ...&#34; ,您会发现此任务无法运行。相反,您必须手动启动它:

在&#34;运行配置&#34;中添加您的任务与this类似,然后当您想要使用自定义名称发布已签名的apk时,您应该可以从herehere运行任务。如果你想生成一个带有默认名称的签名apk(并且仍然增加versionName和versionCode),只需使用&#34;生成签名的APK ...&#34; 选项,就像之前一样。

使用此方法无需在文件的buildTypes部分添加代码。

答案 1 :(得分:1)

好的,这是我的应用程序模块的build.gradle代码:

apply plugin: 'com.android.application'

apply from: 'versionalization.gradle'

def genVersionName = VersionInfo.versionName
def genVersionCode = VersionInfo.versionCode

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.vincestyling.exerciseapk"
        minSdkVersion 10
        targetSdkVersion 22
        versionName genVersionName
        versionCode genVersionCode
    }
}

android.applicationVariants.all { variant ->
    def taskSuffix = variant.name.capitalize()
    def assembleTaskName = "assemble${taskSuffix}"

    if (tasks.findByName(assembleTaskName)) {
        def processAPKTask = tasks.create(name: "process${taskSuffix}Apk", type: Copy) {
            variant.outputs.each { output ->
                from output.outputFile
                into output.outputFile.parent

                def newApkName = android.defaultConfig.applicationId + "-" + variant.buildType.name + "-" + genVersionName + " (" + genVersionCode + ").apk"
                rename ~/(.+)/, newApkName
            }
        }
        tasks[assembleTaskName].finalizedBy processAPKTask
    }
}

应用于头部的versionalization.gradle是我用来增加 VersionInfo 的内容,然后返回两个要使用的值。

task VersionInfo {
    String FACTOR_KEY = "BUILD_NUMBER_FACTOR"

    File buildDir = file("build")
    buildDir.mkdir()

    File factorPropFile = new File(buildDir, "kbuildfactor.prop")

    Properties props = new Properties()
    if (factorPropFile.exists()) {
        props.load(new FileInputStream(factorPropFile))
    }

    int buildNumberFactor = props.get(FACTOR_KEY) as Integer ?: 0
    buildNumberFactor += 1

    props.put(FACTOR_KEY, buildNumberFactor as String)
    props.store(new FileOutputStream(factorPropFile), null)



    String BASE_VERSION_NAME = "BASE_VERSION_NAME"
    String BASE_VERSION_CODE = "BASE_VERSION_CODE"


    File versionPropFile = file("versioning.properties")
    props.load(new FileInputStream(versionPropFile))


    String baseVersionName = props.get(BASE_VERSION_NAME) as String
    Integer baseVersionCode = props.get(BASE_VERSION_CODE) as Integer

    ext.versionName = baseVersionName + "." + buildNumberFactor
    ext.versionCode = baseVersionCode * 1000 + buildNumberFactor
}

它非常简单,读取两个文件以获取必要的字段来构建版本信息。

我们最后复制/重命名最终的APK。

此外,我首先实现了复制/重命名部分,但是当你有任何产品口味时它不会起作用,我把它作为另一种选择粘贴。

android.applicationVariants.all { variant ->
    variant.outputs.each {output ->
        def newApkName = android.defaultConfig.applicationId + "-" + variant.buildType.name + "-" + genVersionName + " (" + genVersionCode + ").apk"

        def oldApkName = "app-${variant.buildType.name}.apk"

        def file = output.outputFile

        output.outputFile = new File(file.parent, file.name.replace(oldApkName, newApkName))
    }
}

答案 2 :(得分:0)

要使用额外的属性扩展,您需要像下面这样定义它们:

ext {
  mVersionCode = 0
  mNextVersionName = ""
}

然后,您只需在上面的任务中使用它们,就可以在您的构建脚本中自由访问它们。