web-dev-qa-db-ja.com

Android Gradle:ビルド時にversionNameを動的に変更する

Android gradle-releaseプラグインのカスタマイズされたバージョンを使用して、Mavenリリースプラグインをエミュレートしようとしています: https://github.com/townsfolk/gradle-release =

興味深いステップは次のとおりです。

  • コミットされていない変更を確認する
  • バージョンコードをステップし、バージョン名から-SNAPSHOTサフィックスを削除します
  • 構築する
  • バージョン名をステップし、次の開発バージョン用に-SNAPSHOTサフィックスを追加します

ただし、生成されたAPKには常に以前のバージョンがあります(つまり、1.0.0ではなく1.0.0-SNAPSHOT)。

バージョン番号はgradle.propertiesに保存され、正しく更新されるため、変更を有効にするにはデータモデルのバージョンも更新する必要があると想定しています。

My Android plugin config:

defaultConfig {
    versionCode versionCode as int  // taken from gradle.properties
    versionName versionName // taken from gradle.properties
    minSdkVersion 10
    targetSdkVersion 19
}

私が試したもの:

preBuild << {
    Android.applicationVariants.each { variant ->
        variant.versionName = versionName
    }
}

ただし、バリアントにはversionNameがありません。

preBuild << {
    Android.buildTypes.each { type ->
        type.versionName = versionName
    }
}

ただし、型にはversionNameがありません。

preBuild << {
    Android.productFlavors.each { flavor ->
        flavor.versionName = versionName
    }
}

しかし、私のアプリにはフレーバーはありません(プレーンデバッグおよびリリースビルドタイプのみ)。

私の代替案は、bash/batスクリプトを記述して、Gradleを呼び出す前にバージョンをステップ実行することです。これは、ビルドのカスタマイズを改善するためにGroovyを使用する目的をほとんど無効にします。

実行段階でAndroid Gradleプラグインでバージョンを動的に更新するにはどうすればよいですか?

33
German

それがbuildTypesの目的です。あなたが説明しているのは、releaseビルド、IMOです。

次に例を示します。assembleDebugを実行すると、スナップショットビルドが提供され、assembleReleaseを実行すると、サフィックスとインクリメントされたバージョン番号のないクリーンビルドが提供されます。次のデバッグビルドでも、インクリメントされた数値が使用されます。

以下は、ファイルがフォルダーに作成された場合の完全に機能するビルドです。フレーバーでも動作するはずですが、それは単なる副産物です:)。 Gradle 2.2.1、Androidプラグイン1.1.3

build.gradle

apply plugin: 'com.Android.application'
apply from: 'auto-version.gradle'

buildscript {
    repositories { jcenter() }
    dependencies { classpath 'com.Android.tools.build:gradle:1.1.3' }
}

Android {
    buildToolsVersion = "21.1.2"
    compileSdkVersion = "Android-21"

    buildTypes {
        debug {
            versionNameSuffix "-SNAPSHOT"
        }
    }
}

println "config code: ${calculateVersionCode()}, name: ${calculateVersionName()}"

src/main/AndroidManifest.xml

<manifest package="com.example" />

auto-version.gradle

ext {
    versionFile = new File(project.rootDir, 'version.properties')
    calculateVersionName = {
        def version = readVersion()
        return "${version['major']}.${version['minor']}.${version['build']}"
    }
    calculateVersionCode = {
        def version = readVersion()
        def major = version['major'] as int // 1..∞
        def minor = version['minor'] as int // 0..99
        def build = version['build'] as int // 0..999
        return (major * 100 + minor) * 1000 + build
    }
}


Properties readVersion() {
    def version = new Properties()
    def stream
    try {
        stream = new FileInputStream(versionFile)
        version.load(stream)
    } catch (FileNotFoundException ignore) {
    } finally {
        if (stream != null) stream.close()
    }
    // safety defaults in case file is missing
    if(!version['major']) version['major'] = "1"
    if(!version['minor']) version['minor'] = "0"
    if(!version['build']) version['build'] = "0"
    return version
}

void incrementVersionNumber() {
    def version = readVersion()

    // careful with the types, culprits: "9"++ = ":", "9" + 1 = "91"
    def build = version['build'] as int
    build++
    version['build'] = build.toString()

    def stream = new FileOutputStream(versionFile)
    try {
        version.store(stream, null)
    } finally {
        stream.close()
    }
}

task incrementVersion {
    description "Increments build counter in ${versionFile}"
    doFirst {
        incrementVersionNumber()
    }
}

if (plugins.hasPlugin('Android') || plugins.hasPlugin('Android-library')) {
    Android {
        defaultConfig {
            versionName = calculateVersionName()
            versionCode = calculateVersionCode()
        }

        afterEvaluate {
            def autoIncrementVariant = { variant ->
                if (variant.buildType.name == buildTypes.release.name) { // don't increment on debug builds
                    variant.preBuild.dependsOn incrementVersion
                    incrementVersion.doLast {
                        variant.mergedFlavor.versionName = calculateVersionName()
                        variant.mergedFlavor.versionCode = calculateVersionCode()
                    }
                }
            }
            if (plugins.hasPlugin('Android')) {
                applicationVariants.all { variant -> autoIncrementVariant(variant) }
            }
            if (plugins.hasPlugin('Android-library')) {
                libraryVariants.all { variant -> autoIncrementVariant(variant) }
            }
        }
    }
}

実行gradle assembleDebug正常にビルドするには、gradle assembleReleaseをインクリメントしてビルドし、gradle incrementVersion単にインクリメントします。 注:gradle assembleassembleDebugassembleReleaseの順序が異なる結果をもたらすため。

buildディレクトリに生成されたファイルをチェックして、値が自分の好みに合っているかどうかを確認します。

手動実行(コメントから)

複数のバリアントがリリースビルドタイプに一致するため、複数のフレーバーが存在する可能性があります。その場合、バージョンが複数回インクリメントされます。元々の質問は、フレーバーがないことでした。バージョン番号をインクリメントするときにさらに制御したい場合は、afterEvaluateブロックを削除して、いつでもincrementVersionタスクを呼び出します。

gradle incrementVersion assembleFreeRelease assemblePaidRelease

(上記の手動実行はテストされていないアイデアです。)

コミットされていない変更を確認する

「コミットされていない変更を確認する」はこの回答ではカバーされていません。これは別のゲームです。 tasks.preBuild.doFirst { /*fail here if uncommited changes*/ }私が正しく理解している場合。しかし、それはバージョン管理に大きく依存しています。詳細については別の質問をしてください!

54
TWiStErRob

コードリビジョンの現在のgitコミットカウントをバージョン名に追加する必要がありました。多くの状況で本当に便利です。私は以下の簡単なgradleファイルになりました

apply plugin: 'com.Android.application'

Android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    def gitCommitCount = "git rev-list HEAD --count".execute().text.trim()

    defaultConfig {
        applicationId "my.app.package.name"
        minSdkVersion 16
        targetSdkVersion 21
        versionCode 6
        versionName "0.8"
    }

    buildTypes {

        debug {
            versionNameSuffix ".${gitCommitCount}"
        }

        release {
            versionNameSuffix ".${gitCommitCount}"
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-Android-optimize.txt'), 'proguard-rules.pro'

        }
    }
}

GitCommitCountと同様に、独自の変数を生成してバージョン名をカスタマイズできます。私は端末コマンドを実行してその結果を変数に保存しているだけです。

12
Javanator

これは、versionNameを完全に変更する方法に関する質問に直接対処するものではありませんが、buildTypesにサフィックスを追加するために使用するものです。

defaultConfig {
    versionName "1.0"
}

buildTypes {
    debug {
        versionNameSuffix "-SNAPSHOT"
    }
}
10
Tanis.7x

Javanator's answer を使用し、それを少し変更して、コミットカウントが名前の変更に役立つだけでなく、バ​​ージョンコードも一意のままになるようにしました。ここに私がやったことのサンプルがあります(たぶんいくつかのことを最適化できますが、それでも私のために仕事をします):

Android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    def gitCommitCount = "git rev-list HEAD --count".execute().text.trim().toBigInteger()
    project.ext.set("versionCode", gitCommitCount)
    project.ext.set("versionNameSuffix", "(${gitCommitCount})")

    defaultConfig {
        applicationId "my.app.package.name"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode  project.versionCode
        versionName "1.0"
        versionNameSuffix project.versionNameSuffix
        setProperty("archivesBaseName", "MyProject-$versionName")
        ....
    }

    signingConfigs {
        config {
            .........
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.config
        }
    }

    packagingOptions {
        .....
    }

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    output.outputFile.parent,
                    output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
        }
    }
}

Edit:最後のビットも次のようになります

    applicationVariants.all { variant ->
    if (variant.name.contains('release')) {
        variant.outputs.each { output ->
            variant.outputs.all {
                outputFileName = "MyProject-${variant.versionName}${variant.versionCode}.apk"
            }
        }
    }
}
5
Neil B

私は、リリースビルドと非リリースビルドのビルドロジックを別々にするという同様のニーズに直面していました。異なるバージョン管理とは別に、異なるリポジトリ、さらには異なるリポジトリのセットを使用する必要がありました。

使用可能なプラグインにはどれも必要な機能がすべて備わっていなかったため、コマンドライン引数という単純なアプローチに基づいて独自のソリューションを開発しました。

次のようなgradleビルドスクリプトを呼び出すときに、コマンドラインパラメーターを渡すことができます。

gradle build -PmyParameter = myValue

または私の場合

gradle build -PisRelease = true

Gradleはそれを解析し、プロジェクトオブジェクトのプロパティとして自動的に使用可能になります。次のように使用できます。

if (project.isRelease) {
        // Here be the logic!
}

このロジックを別のプラグインに抽出し、さまざまなプロジェクトで正常に使用しています。

これはあなたの質問に直接答えるものではありませんが、問題と考えられる別の解決策について考えるための別の角度をお伝えしたいと思います。

2
Sean