web-dev-qa-db-fra.com

Android Gradle: changer dynamiquement VersionName au moment de la construction

J'essaie d'émuler le plugin de sortie Maven dans Android en utilisant une version personnalisée du plugin de sortie gradle: https://github.com/townsfolk/gradle-release =

Les étapes intéressantes sont:

  • Vérifier les modifications non validées
  • Étape code de version et suppression du suffixe -SNAPSHOT du nom de la version
  • Construire
  • Étape nom de la version et ajout du suffixe -SNAPSHOT pour la prochaine version de développement

Cependant, l'APK généré a toujours les versions précédentes (c'est-à-dire 1.0.0-SNAPSHOT au lieu de 1.0.0).

Les numéros de version sont stockés et correctement mis à jour dans gradle.properties, je suppose donc que je dois également mettre à jour les versions dans le modèle de données pour que les modifications prennent effet.

Ma Android:

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

Choses que j'ai essayées:

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

Mais il n'y a pas de versionName dans une variante.

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

Mais il n'y a pas de versionName dans un type.

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

Mais il n'y a pas de saveurs dans mon application (types de version de débogage et de version simples uniquement).

Mon alternative est d'écrire un script bash/bat pour passer aux versions avant d'invoquer Gradle, ce qui va à peu près à l'encontre du but d'utiliser Groovy pour améliorer la personnalisation de la construction.

Comment puis-je mettre à jour les versions dynamiquement dans le Android plugin Gradle dans la phase d'exécution?

33
German

C'est à cela que servent buildTypes. Ce que vous décrivez est une construction release, IMO.

Voici un exemple: lors de l'exécution de assembleDebug, il vous donnera une version instantanée, et l'exécution de assembleRelease vous donnera une version propre sans suffixe et numéro de version incrémenté. La prochaine version de débogage utilisera également le numéro incrémenté.

Ce qui suit est une version entièrement fonctionnelle lorsque les fichiers sont créés dans un dossier. Cela devrait également fonctionner avec des saveurs, mais ce n'est qu'un produit secondaire :). Gradle 2.2.1, Android plugin 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) }
            }
        }
    }
}

Exécutez gradle assembleDebug pour construire normalement, gradle assembleRelease pour incrémenter et construire, et gradle incrementVersion pour simplement incrémenter. Remarque: soyez prudent avec gradle assemble car l'ordre de assembleDebug et assembleRelease donnera des résultats différents.

Vérifiez les fichiers générés dans le répertoire build pour voir si les valeurs vous conviennent.

Exécution manuelle (à partir des commentaires)

Il est possible que vous ayez plusieurs versions, auquel cas la version est incrémentée plusieurs fois car plusieurs variantes correspondent au type de build de la version. La question d'origine était sans saveurs. Si vous souhaitez avoir plus de contrôle lorsque le numéro de version est incrémenté, supprimez simplement le bloc afterEvaluate et appelez la tâche incrementVersion quand vous le souhaitez:

gradle incrementVersion assembleFreeRelease assemblePaidRelease

(L'exécution manuelle ci-dessus est une idée non testée.)

Vérifier les modifications non validées

Les "Vérifier les modifications non validées" ne sont pas couvertes dans cette réponse, c'est un autre jeu. Vous pouvez vous connecter à tasks.preBuild.doFirst { /*fail here if uncommited changes*/ } Si je comprends bien. Mais cela dépend fortement de votre contrôle de version. Posez une autre question pour en savoir plus!

54
TWiStErRob

J'avais besoin d'ajouter le décompte de validation git actuel de la révision de code au nom de la version. C'est vraiment pratique dans de nombreuses situations. Je me suis retrouvé avec un fichier gradle ci-dessous

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'

        }
    }
}

Semblable à gitCommitCount, vous pouvez générer vos propres variables pour personnaliser le nom de la version. Comme je suis juste en train d'exécuter une commande de terminal pour stocker son résultat dans une variable.

12
Javanator

Cela ne répond pas directement à votre question de savoir comment modifier complètement le versionName, mais c'est ce que j'utilise pour ajouter un suffixe à mes buildTypes:

defaultConfig {
    versionName "1.0"
}

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

Je viens d'utiliser réponse de Javanator et de le modifier un peu pour que le nombre de validations aide non seulement à changer le nom, mais aussi à s'assurer que le code de version reste également unique. Voici un échantillon de ce que j'ai fait (Peut-être que deux choses peuvent être optimisées, mais font néanmoins le travail pour moi):

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: Le dernier bit pourrait aussi être comme

    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

J'étais confronté à un besoin similaire d'avoir une logique de génération distincte pour les versions publiées et non publiées. Mis à part les versions différentes, j'ai dû utiliser un ensemble différent de dépendances, même différents référentiels.

Aucun des plugins disponibles n'avait toutes les fonctionnalités dont j'avais besoin, j'ai donc développé ma propre solution, basée sur une approche simple - argument de ligne de commande.

Vous pouvez passer un paramètre de ligne de commande lors de l'appel du script de construction gradle comme ceci:

gradle build -PmyParameter = myValue

ou dans mon cas

gradle build -PisRelease = true

Gradle va l'analyser et il serait automatiquement disponible en tant que propriété de l'objet projet. Vous pouvez ensuite l'utiliser comme ceci:

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

J'ai extrait cette logique dans un plugin séparé et je l'ai utilisée avec succès dans différents projets.

Bien que cela ne réponde pas directement à votre question, j'espère que je vous ai donné un autre angle pour réfléchir au problème et une autre solution possible.

2
Sean