Come impostare versionName nel nome file APK usando Gradle?


169

Sto cercando di impostare un numero di versione specifico nel nome file APK generato automaticamente dal gradle.

Ora il grado genera myapp-release.apkma voglio che assomigli a qualcosa del genere myapp-release-1.0.apk.

Ho provato a rinominare le opzioni che sembrano disordinate. C'è un modo semplice per fare questo?

buildTypes {
    release {
       signingConfig signingConfigs.release
       applicationVariants.each { variant ->
       def file = variant.outputFile
       variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" +    defaultConfig.versionName + ".apk"))
    }
}

Ho provato il codice sopra senza fortuna. Eventuali suggerimenti? (usando il grado 1.6)

Risposte:


225

Devo solo cambiare il nome della versione in un unico posto. Anche il codice è semplice.

Gli esempi seguenti creeranno file apk denominati MyCompany-MyAppName-1.4.8-debug.apk o MyCompany-MyAppName-1.4.8-release.apk a seconda della variante di build selezionata.

Si noti che questa soluzione funziona sia su APK sia su pacchetti di app (file .aab) .

Vedi anche: Come modificare il nome del file di mappatura proguard in gradle per il progetto Android

Soluzione per plugin Gradle recenti

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"
    defaultConfig {
        applicationId "com.company.app"
        minSdkVersion 13
        targetSdkVersion 21
        versionCode 14       // increment with every release
        versionName '1.4.8'   // change with every release
        setProperty("archivesBaseName", "MyCompany-MyAppName-$versionName")
    }
}

La soluzione sopra è stata testata con le seguenti versioni di plug-in Android Gradle:

  • 3.5.2 (novembre 2019)
  • 3.3.0 (gennaio 2019)
  • 3.1.0 (marzo 2018)
  • 3.0.1 (novembre 2017)
  • 3.0.0 (ottobre 2017)
  • 2.3.2 (maggio 2017)
  • 2.3.1 (aprile 2017)
  • 2.3.0 (febbraio 2017)
  • 2.2.3 (dicembre 2016)
  • 2.2.2
  • 2.2.0 (settembre 2016)
  • 2.1.3 (agosto 2016)
  • 2.1.2
  • 2.0.0 (aprile 2016)
  • 1.5.0 (2015/11/12)
  • 1.4.0-beta6 (2015/10/05)
  • 1.3.1 (2015/08/11)

Aggiornerò questo post non appena usciranno nuove versioni.

Soluzione testata solo sulle versioni 1.1.3-1.3.0

La seguente soluzione è stata testata con le seguenti versioni di plug-in Android Gradle:

file gradle app:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"
    defaultConfig {
        applicationId "com.company.app"
        minSdkVersion 13
        targetSdkVersion 21
        versionCode 14       // increment with every release
        versionName '1.4.8'   // change with every release
        archivesBaseName = "MyCompany-MyAppName-$versionName"
    }
}

11
Penso che questo sia l'approccio giusto invece di scrivere un'altra attività per rinominare i file.
Nandish A

5
cambia in archivesBaseName = "MyCompany-MyAppName- $ versionName" se hai un disturbo ossessivo compulsivo e non vuoi che AS ti avverta del +
ligi

4
Grande scoperta, ma non funziona bene con sapori con diversi codici di versione. Finiscono tutti con lo stesso codice di versione.
Weston,

2
C'è un modo per aggiungere variant.buildType.nameal nome? So che questo non è realmente correlato alla configurazione predefinita, ma sto cercando di capire come rimuovere l' variantOutput.getAssemble()avvertimento obsoleto
Allan W

2
È possibile rimuovere dal cognome dell'apk '-debug' / '-release'?
ilyamuromets,

173

Questo ha risolto il mio problema: usare al applicationVariants.allposto diapplicationVariants.each

buildTypes {
      release {
        signingConfig signingConfigs.release
        applicationVariants.all { variant ->
            def file = variant.outputFile
            variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk")) 
        }
    }       
}

Aggiornare:

Quindi sembra che questo non funzioni con le versioni 0.14+ del plug-in Android Studio Gradle.

Questo è il trucco (riferimento da questa domanda ):

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

3
Sai come farlo funzionare se ho una configurazione versionNamedefinita AndroidManifest.xmlanziché gradle? Mi dà myapp-release-null.apkadesso.
Iwo Banas,

1
Questa risposta non funziona con le versioni 0.14+ del plugin gradle. Eventuali aggiornamenti per lavorare con quelli?
Argyle,

1
@withoutclass Ho fatto questa domanda come una sua domanda e ho ottenuto risposta qui: stackoverflow.com/questions/27068505/…
Argyle

2
Per le persone che eseguono l'aggiornamento a Grado 4: passare eacha alle output.outputFilea outputFileName. Se qualcuno conferma che funziona, può essere modificato nella risposta :)
PHPirate

6
@PHPirate: quasi funziona:Error:(34, 0) Cannot set the value of read-only property 'name'
Mooing Duck il

47

(EDITED per funzionare con Android Studio 3.0 e Gradle 4)

Stavo cercando un'opzione di ridenominazione del nome di file apk più complessa e ho scritto questo nella speranza che sia utile per chiunque altro. Rinomina l'apk con i seguenti dati:

  • gusto
  • tipo di build
  • versione
  • Data

Mi ci sono voluti un po 'di ricerche nelle classi elementari e un po' di copia / incolla da altre risposte. Sto usando il grado 3.1.3 .

Nel build.gradle:

android {

    ...

    buildTypes {
        release {
            minifyEnabled true
            ...
        }
        debug {
            minifyEnabled false
        }
    }

    productFlavors {
        prod {
            applicationId "com.feraguiba.myproject"
            versionCode 3
            versionName "1.2.0"
        }
        dev {
            applicationId "com.feraguiba.myproject.dev"
            versionCode 15
            versionName "1.3.6"
        }
    }

    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def project = "myProject"
            def SEP = "_"
            def flavor = variant.productFlavors[0].name
            def buildType = variant.variantData.variantConfiguration.buildType.name
            def version = variant.versionName
            def date = new Date();
            def formattedDate = date.format('ddMMyy_HHmm')

            def newApkName = project + SEP + flavor + SEP + buildType + SEP + version + SEP + formattedDate + ".apk"

            outputFileName = new File(newApkName)
        }
    }
}

Se compili oggi (13-10-2016) alle 10:47, otterrai i seguenti nomi di file a seconda del sapore e del tipo di build che hai scelto:

  • dev debug : myProject_ dev_debug_1.3.6 _131016_1047.apk
  • versione dev : myProject_ dev_release_1.3.6 _131016_1047.apk
  • prod debug : myProject_ prod_debug_1.2.0 _131016_1047.apk
  • rilascio prod : myProject_ prod_release_1.2.0 _131016_1047.apk

Nota: il nome apk della versione non allineata è ancora quello predefinito.


Ottima soluzione L'ho provato ed è perfetto per il mio problema. Grazie!
Pabel,

è possibile utilizzare lo stesso approccio in Xamarin Studio?
Alessandro Caliaro,

Sarebbe bello se fosse possibile, ma sto iniziando ora un corso di Xamarin e non ho ancora abbastanza pratica con esso per sapere se è possibile o no. Farò questa domanda e tornerò di nuovo qui.
Fer

Commento dell'insegnante del corso: "esiste un'opzione in cui è possibile utilizzare i comandi per modificare il nome dei file generati". Pertanto, l'approccio da utilizzare da Xamarin deve essere diverso da quello che ho scritto per Android Studio, mi dispiace.
Fer

3
Per risolvere l'errore Impossibile impostare il valore della proprietà di sola lettura "outputFile" , come indicato in un commento precedente per la necessità di "passare eacha alle output.outputFilein outputFileName" - questo post fornisce alcuni dettagli al riguardo: stackoverflow.com/a/44265374/2162226
Gene Bo,

19

Per riassumere, per coloro che non sanno come importare il pacchetto in build.gradle(come me), utilizzare quanto segue buildTypes,

buildTypes {
      release {
        signingConfig signingConfigs.release
        applicationVariants.all { variant ->
            def file = variant.outputFile
            def manifestParser = new com.android.builder.core.DefaultManifestParser()
            variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile) + ".apk")) 
        }
    }       
}

===== MODIFICA =====

Se imposti il ​​tuo versionCodee versionNamenel tuo build.gradlefile in questo modo:

defaultConfig {
    minSdkVersion 15
    targetSdkVersion 19
    versionCode 1
    versionName "1.0.0"
}

Dovresti impostarlo in questo modo:

buildTypes {   
        release {
            signingConfig signingConfigs.releaseConfig
            applicationVariants.all { variant ->
                def file = variant.outputFile
                variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"))
            }
        }
}


====== MODIFICA con Android Studio 1.0 ======

Se si utilizza Android Studio 1.0, verrà visualizzato un errore simile al seguente:

Error:(78, 0) Could not find property 'outputFile' on com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated@67e7625f.

È necessario modificare la build.Typesparte in questo:

buildTypes {
        release {
            signingConfig signingConfigs.releaseConfig
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"))
                }
            }
        }
    }

Funziona benissimo. Tuttavia, poiché incremento la mia versione manifest nella build gradle, creerà un APK con il valore precedente (pre-incremento). Qualche modo per assicurarsi che ciò abbia effetto dopo che lo script gradle incrementa il numero di versione?
Guy

1
@Guy Mi dispiace aver impiegato così tanto tempo. Ho modificato la risposta, vedi se riesce a risolvere il tuo problema.
Wesley,

17

Se non si specifica versionName nel blocco defaultConfig, defaultConfig.versionNamesi verificherànull

per ottenere versionName da manifest puoi scrivere il seguente codice in build.gradle:

import com.android.builder.DefaultManifestParser

def manifestParser = new DefaultManifestParser()
println manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile)

7
Credo che con le versioni successive di Gradle, ora sia com.android.builder.core.DefaultManifestParser
Ryan S

8

Nel mio caso, volevo solo trovare un modo per automatizzare la generazione di apknomi diversi releasee debugvarianti. Sono riuscito a farlo facilmente inserendo questo frammento come figlio di android:

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def appName = "My_nice_name_"
        def buildType = variant.variantData.variantConfiguration.buildType.name
        def newName
        if (buildType == 'debug'){
            newName = "${appName}${defaultConfig.versionName}_dbg.apk"
        } else {
            newName = "${appName}${defaultConfig.versionName}_prd.apk"
        }
        output.outputFile = new File(output.outputFile.parent, newName)
    }
}

Per il nuovo plug-in Android 3.0 Gradle puoi fare qualcosa del genere:

 applicationVariants.all { variant ->
    variant.outputs.all {
        def appName = "My_nice_name_"
        def buildType = variant.variantData.variantConfiguration.buildType.name
        def newName
        if (buildType == 'debug'){
            newName = "${appName}${defaultConfig.versionName}_dbg.apk"
        } else {
            newName = "${appName}${defaultConfig.versionName}_prd.apk"
        }
        outputFileName = newName
    }
}

Questo produce qualcosa di simile: My_nice_name_3.2.31_dbg.apk


6

Un'altra alternativa è utilizzare quanto segue:

String APK_NAME = "appname"
int VERSION_CODE = 1
String VERSION_NAME = "1.0.0"

project.archivesBaseName = APK_NAME + "-" + VERSION_NAME;

    android {
      compileSdkVersion 21
      buildToolsVersion "21.1.1"

      defaultConfig {
        applicationId "com.myapp"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode VERSION_CODE
        versionName VERSION_NAME
      }

       .... // Rest of your config
}

Questo imposterà "appname-1.0.0" su tutti i tuoi output apk.


Siamo spiacenti non funziona (più): No such property: archivesBaseName for class: org.gradle.api.internal.project.DefaultProject_Decorated
Martin

Quale versione graduale stai usando?
Marco RS,

6

Grado 6+

Ora sto usando il seguente in Android Studio 4.0 e Grado 6.4:

android {
    defaultConfig {
        applicationId "com.mycompany.myapplication"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 15
        versionName "2.1.1"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            applicationVariants.all { variant ->
                variant.outputs.all {
                    outputFileName = "ApplicationName-${variant.name}-${variant.versionName}.apk"
                }
            }
        }
    }
}

Grado 4

La sintassi è leggermente cambiata in Gradle 4 (Android Studio 3+) (da output.outputFilea outputFileName, l'idea di questa risposta è ora:

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def newName = outputFileName
            newName.replace(".apk", "-${variant.versionName}.apk")
            outputFileName = new File(newName)
        }
    }
}

Qualche idea su come risolvere questo problema per il livello 6?
spartygw,

@spartygw Aggiornato la risposta
PHPirate il

5

Il modo giusto per rinominare l'apk, come per la risposta @Jon

defaultConfig {
        applicationId "com.irisvision.patientapp"
        minSdkVersion 24
        targetSdkVersion 22
        versionCode 2  // increment with every release
        versionName "0.2" // change with every release
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        //add this line
        archivesBaseName = "AppName-${versionName}-${new Date().format('yyMMdd')}"
    }   

O un altro modo con cui puoi ottenere gli stessi risultati

android {
    ...

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            def formattedDate = new Date().format('yyMMdd')
            outputFileName = "${outputFileName.replace(".apk","")}-v${defaultConfig.versionCode}-${formattedDate}.apk"
        }
    }
}

Bello su questo! Mi piace di più rispetto ad altri modi in cui lo sto attualmente facendo.
Droid Chris,

3

Esistono molte risposte corrette o complete o dopo alcune modifiche. Ma aggiungerò comunque il mio dato che stavo avendo il problema con tutti loro perché stavo usando gli script per generare dinamicamente VersionName e VersionCode collegandomi preBuildall'attività.

Se stai usando un approccio simile, questo è il codice che funzionerà:

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

Per spiegare: Dato che io sono imperativi codice di versione e nome nella prima azione del preBuilddevo aggiungere il file rinominando la fine di questo compito. Quindi ciò che farà Gradle in questo caso è:

Iniettare il codice versione / nome-> esegui azioni preBuild -> sostituisci nome per apk


Dove stai impostando le variabili versionCode e versionName generate?
Marte,

Come ricordo, è stato fatto all'interno del nostro plugin gradle personalizzato. La sua esecuzione è stata chiamata come ultima azione dell'attività preBuild.
Igor Čordaš,

2
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            output.outputFileName = output.outputFileName.replace(".apk", "-${variant.versionName}.apk")
        }
    }

Mentre questo frammento di codice può risolvere la domanda, inclusa una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e che queste persone potrebbero non conoscere i motivi del tuo suggerimento sul codice.
Rosário Pereira Fernandes,

1

Nel mio caso, risolvo questo errore in questo modo

aggiungendo un SUFFIX alla versione di debug, in questo caso aggiungo il testo "-DEBUG" alla mia distribuzione di debug

 buildTypes {
        release {

            signingConfig signingConfigs.release
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'


        }
        debug {

            defaultConfig {
                debuggable true

                versionNameSuffix "-DEBUG"
            }
        }
    }

Questo non cambia il nome del file APK.
Tom,

1
Questo è un bel consiglio, in realtà. Non nella domanda giusta, ma buona. Dove posso leggere di più al riguardo? È possibile utilizzare in versionNameSuffixbase al ramo GIT? Ad esempio, se non è su "master", hai sempre un suffisso, anche se è una versione di rilascio
sviluppatore Android

0

Per le versioni più recenti di gradle puoi utilizzare il seguente frammento:

Imposta prima la posizione del manifest dell'applicazione

 sourceSets {
        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
        {
    }

E più tardi in build.gradle

import com.android.builder.core.DefaultManifestParser

def getVersionName(manifestFile) {
    def manifestParser = new DefaultManifestParser();
    return manifestParser.getVersionName(manifestFile);
}

def manifestFile = file(android.sourceSets.main.manifest.srcFile);
def version = getVersionName(manifestFile)

buildTypes {
    release {
       signingConfig signingConfigs.release
       applicationVariants.each { variant ->
       def file = variant.outputFile
       variant.outputFile = new File(file.parent, file.name.replace(".apk", "-" +    versionName + ".apk"))
    }
}

Regola se hai manifest diversi per tipo di build. ma dal momento che ho quello singolo - funziona perfettamente per me.


è possibile aggiungere una stringa da un file di classe al nome apk ??
Upendra Shah,

0

A partire da Android Studio 1.1.0, ho scoperto che questa combinazione ha funzionato nel corpo Android del build.gradlefile. Questo se non riesci a capire come importare i dati del file XML manifest. Vorrei che fosse più supportato da Android Studio, ma basta giocare con i valori fino a ottenere l'output del nome apk desiderato:

defaultConfig {
        applicationId "com.package.name"
        minSdkVersion 14
        targetSdkVersion 21
        versionCode 6
        versionName "2"
    }
    signingConfigs {
        release {
            keyAlias = "your key name"
        }
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            signingConfig signingConfigs.release
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace("app-release.apk", "appName_" + versionName + ".apk"))
                }
            }
        }
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.