Android Gradle: changer de version dynamique au moment de la construction

j'essaie d'imiter Maven release plugin dans Android en utilisant une version personnalisée de gradle-release plugin: https://github.com/townsfolk/gradle-release

L'intéressant, les étapes sont les suivantes:

  • vérifier les changements non engagés
  • Etape code de version et retirez -INSTANTANÉ suffixe du nom de la version
  • Construire
  • Étape nom de la version et ajoutez -INSTANTANÉ suffixe pour le prochain développement version

cependant L'APK générée a toujours les versions précédentes (i.e. 1.0.0-SNAPSHOT au lieu de 1.0.0).

les numéros de Version sont stockés et correctement mis à jour dans gradle.propriétés, donc je suppose que je dois mettre à jour les versions dans le modèle de données aussi bien pour les changements à prendre effet.

Mon android plugin config:

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

Choses que j'ai essayé:

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

mais il n'y a pas de versionName dans un 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 (débogage simple et les types de construction de libération seulement).

mon alternative est d'écrire un script bash / bat pour faire avancer les versions avant d'invoquer Gradle, ce qui va à peu près à l'encontre du but de L'utilisation de Groovy pour améliorer la personnalisation de la construction.

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

28
demandé sur German 2014-01-28 22:57:10

5 réponses

c'est ce Que buildTypes sont en pour les. Ce que vous décrivez est un release construction, IMO.

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

ce qui suit est une construction entièrement fonctionnelle lorsque les fichiers sont créés dans un dossier. Ça devrait aussi marcher avec les saveurs, mais c'est juste d'un côté produit :). Gradle 2.2.1, Android plugin 1.1.3

construire.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écuter gradle assembleDebug pour construire normalement, gradle assembleRelease pour incrémenter et de construire, et gradle incrementVersion pour incrémenter seulement. Note: attention, avec gradle assemble parce que l'ordre de assembleDebug et assembleRelease donnera des résultats différents.

Vérifier les fichiers générés dans le build répertoire pour voir si les valeurs sont à votre goût.

Manuel d'exécution (de commentaires)

il est possible que vous ayez plusieurs saveurs, auquel cas la version est incrémentée plusieurs fois parce que plusieurs variantes correspondent au type de construction de la version. La question originale n'était pas pour les saveurs. Si vous voulez avoir plus de contrôle lorsque le numéro de version est incrémenté seulement de supprimer les afterEvaluate bloc et appeler le incrementVersion tâche chaque fois que vous veux:

gradle incrementVersion assembleFreeRelease assemblePaidRelease

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

vérifier les changements non engagés

les "Check uncommitted changes" ne sont pas couverts dans cette réponse, c'est un autre jeu. Vous pourriez crochet 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 plus!

53
répondu TWiStErRob 2015-04-24 18:33:12

ceci ne répond pas directement à votre question sur la façon de changer complètement le versionName, mais c'est ce que j'utilise pour ajouter un suffixe pour mes types de construction:

defaultConfig {
    versionName "1.0"
}

buildTypes {
    debug {
        versionNameSuffix "-SNAPSHOT"
    }
}
9
répondu Tanis.7x 2014-01-28 19:00:48

j'ai dû ajouter le compte de propagation git actuel de la révision du code au nom de la version. Son réel à portée de main dans de nombreuses situation. Je me suis retrouvé avec le fichier gradle simple 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'

        }
    }
}

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

9
répondu Javanator 2016-01-06 09:09:21

j'ai simplement utilisé réponse de Javanator et l'a modifié un peu de sorte que commit count aide non seulement à changer le nom mais aussi à s'assurer que le code de version reste aussi unique. Voici un exemple de ce que j'ai fait (peut-être quelques choses peuvent être optimisées, mais fait 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 également être de la forme

    applicationVariants.all { variant ->
    if (variant.name.contains('release')) {
        variant.outputs.each { output ->
            variant.outputs.all {
                outputFileName = "MyProject-${variant.versionName}${variant.versionCode}.apk"
            }
        }
    }
}
4
répondu Neil B 2018-09-04 12:31:36

j'étais confronté au même besoin d'avoir une logique de construction séparée pour les constructions de version et de non-Version. En plus d'utiliser des versions différentes, j'ai dû utiliser un ensemble différent de dépendances, même des dépôts différents.

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

vous pouvez passer un paramètre de ligne de commande en invoquant le script de construction de gradle comme ceci:

gradle build -PmyParameter=myValue

ou dans mon cas

gradle build -PisRelease=true

Grad le comparera, et il sera automatiquement disponible comme propriété de l'objet du 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é avec succès à travers 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 sur le problème et un autre possible solution.

2
répondu Sean 2014-10-02 11:07:02