Wie setze ich versionName im APK-Dateinamen mit gradle?

169

Ich versuche, eine bestimmte Versionsnummer im automatisch generierten APK-Dateinamen von gradle festzulegen.

Jetzt erzeugt Gradle, myapp-release.apkaber ich möchte, dass es ungefähr so aussieht myapp-release-1.0.apk.

Ich habe versucht, Optionen umzubenennen, die chaotisch erscheinen. Gibt es eine einfache Möglichkeit, dies zu tun?

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"))
    }
}

Ich habe den obigen Code ohne Glück ausprobiert. Irgendwelche Vorschläge? (mit Gradle 1.6)

codaR0y
quelle

Antworten:

225

Ich muss den Versionsnamen nur an einer Stelle ändern. Der Code ist auch einfach.

In den folgenden Beispielen werden je nach ausgewählter Build-Variante Apk-Dateien mit dem Namen MyCompany-MyAppName-1.4.8-debug.apk oder MyCompany-MyAppName-1.4.8-release.apk erstellt .

Beachten Sie, dass diese Lösung sowohl für APK- als auch für App-Bundles (.aab-Dateien) funktioniert. .

Siehe auch: So ändern Sie den Namen der Proguard-Zuordnungsdatei in Gradle für Android-Projekte

Lösung für das aktuelle Gradle Plugin

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")
    }
}

Die obige Lösung wurde mit den folgenden Android Gradle Plugin-Versionen getestet:

  • 3.5.2 (November 2019)
  • 3.3.0 (Januar 2019)
  • 3.1.0 (März 2018)
  • 3.0.1 (November 2017)
  • 3.0.0 (Oktober 2017)
  • 2.3.2 (Mai 2017)
  • 2.3.1 (April 2017)
  • 2.3.0 (Februar 2017)
  • 2.2.3 (Dezember 2016)
  • 2.2.2
  • 2.2.0 (September 2016)
  • 2.1.3 (August 2016)
  • 2.1.2
  • 2.0.0 (April 2016)
  • 1.5.0 (12.11.2015)
  • 1.4.0-beta6 (05.10.2015)
  • 1.3.1 (11.08.2015)

Ich werde diesen Beitrag aktualisieren, sobald neue Versionen herauskommen.

Lösung nur in den Versionen 1.1.3-1.3.0 getestet

Die folgende Lösung wurde mit den folgenden Android Gradle Plugin-Versionen getestet:

  • 1.3.0 (30.07.2015) - Funktioniert nicht, Fehler soll in 1.3.1 behoben werden
  • 1.2.3 (21.07.2015)
  • 1.2.2 (28.04.2015)
  • 1.2.1 (27.04.2015)
  • 1.2.0 (26.04.2015)
  • 1.2.0-beta1 (25.03.2015)
  • 1.1.3 (06.03.2015)

App Gradle-Datei:

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"
    }
}
Jon
quelle
11
Ich denke, dies ist der richtige Ansatz, anstatt eine andere Aufgabe zum Umbenennen von Dateien zu schreiben.
Nandish A
5
Wechseln Sie einfach zu archivesBaseName = "MyCompany-MyAppName- $ versionName", wenn Sie eine OCD haben und nicht möchten, dass AS Sie vor dem +
ligi
4
Toller Fund, funktioniert aber nicht gut mit Geschmacksrichtungen mit unterschiedlichen Versionscodes. Sie haben alle den gleichen Versionscode.
Weston
2
Gibt es eine Möglichkeit variant.buildType.name, den Namen zu ergänzen ? Ich weiß, dass dies nicht wirklich mit der Standardkonfiguration zusammenhängt, aber ich versuche herauszufinden, wie die veraltete variantOutput.getAssemble()Warnung entfernt werden kann
Allan W
2
Ist es möglich, den letzten '-debug' / '-release' aus dem apk-Namen zu entfernen?
Ilyamuromets
173

Dies löste mein Problem: Verwenden applicationVariants.allstattapplicationVariants.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")) 
        }
    }       
}

Aktualisieren:

Es scheint also, dass dies mit mehr als 0.14+ Versionen des Android Studio Gradle Plugins nicht funktioniert.

Dies macht den Trick (Referenz aus dieser Frage ):

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    output.outputFile.parent,
                    output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
        }
    }
}
codaR0y
quelle
3
Wissen Sie, wie es funktioniert, wenn ich eine versionNamedefinierte in AndroidManifest.xmlanstelle von gradle config habe? Es gibt mir myapp-release-null.apkjetzt.
Iwo Banas
1
Diese Antwort funktioniert nicht mit Versionen ab 0.14 des Gradle-Plugins. Gibt es Updates, um damit zu arbeiten?
Argyle
1
@withoutclass Ich habe dies als eigene Frage gestellt und hier beantwortet: stackoverflow.com/questions/27068505/…
Argyle
2
Für Benutzer, die auf Gradle 4 aktualisieren: Wechseln Sie eachzu allund output.outputFilezu outputFileName. Wenn jemand bestätigt, dass dies funktioniert, kann es in die Antwort bearbeitet werden :)
PHPirate
6
@ PHPirate: funktioniert fast:Error:(34, 0) Cannot set the value of read-only property 'name'
Mooing Duck
47

(BEARBEITET für Android Studio 3.0 und Gradle 4)

Ich suchte nach einer komplexeren Option zum Umbenennen von apk-Dateinamen und schrieb diese in der Hoffnung, dass sie für alle anderen hilfreich ist. Es benennt die apk mit folgenden Daten um:

  • Geschmack
  • Build-Typ
  • Ausführung
  • Datum

Ich habe ein bisschen in Gradle-Klassen recherchiert und ein bisschen aus anderen Antworten kopiert / eingefügt. Ich benutze Gradle 3.1.3 .

In der 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)
        }
    }
}

Wenn Sie heute (13-10-2016) um 10:47 kompilieren, erhalten Sie die folgenden Dateinamen, abhängig von der gewählten Variante und dem gewählten Build-Typ:

  • dev debug : myProject_ dev_debug_1.3.6 _131016_1047.apk
  • dev Release : myProject_ dev_release_1.3.6 _131016_1047.apk
  • prod Debug : myProject_ prod_debug_1.2.0 _131016_1047.apk
  • prod Release : myProject_ prod_release_1.2.0 _131016_1047.apk

Hinweis: Der apk-Name der nicht ausgerichteten Version ist immer noch der Standardname.

Fer
quelle
Tolle Lösung. Ich habe es versucht und es ist perfekt für mein Problem. Vielen Dank!
Pabel
Ist es möglich, denselben Ansatz in Xamarin Studio zu verwenden?
Alessandro Caliaro
Es wäre großartig, wenn es möglich wäre, aber ich beginne gerade einen Xamarin-Kurs und habe immer noch nicht genug Übung damit, um zu wissen, ob es möglich ist oder nicht. Ich werde diese Frage stellen und wieder hierher kommen.
Fer
Kommentar des Kurslehrers: "Es gibt eine Option, bei der Sie Befehle verwenden können, um den Namen der generierten Dateien zu ändern." Daher muss sich der Ansatz für die Verwendung von Xamarin von dem unterscheiden, den ich für Android Studio geschrieben habe.
Fer
3
So beheben Sie den Fehler Der Wert der schreibgeschützten Eigenschaft 'outputFile' kann nicht festgelegt werden - wie in einem früheren Kommentar erwähnt, weil " eachzu allund output.outputFilezu outputFileName" geändert werden muss - enthält dieser Beitrag einige Details dazu: stackoverflow.com/a/44265374/2162226
Gene Bo
18

Um zusammenzufassen, für diejenigen, die nicht wissen, wie man ein Paket importiert build.gradle(wie ich), verwenden Sie Folgendes 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")) 
        }
    }       
}

===== BEARBEITEN =====

Wenn Sie Ihr versionCodeund versionNamein Ihrer build.gradleDatei wie folgt einstellen :

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

Sie sollten es so einstellen:

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"))
            }
        }
}


====== BEARBEITEN mit Android Studio 1.0 ======

Wenn Sie Android Studio 1.0 verwenden, wird folgende Fehlermeldung angezeigt:

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

Sie sollten das build.TypesTeil folgendermaßen ändern :

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"))
                }
            }
        }
    }
Wesley
quelle
Das funktioniert super. Da ich jedoch meine Manifestversion im Gradle-Build inkrementiere, wird eine APK mit dem älteren Wert (vor dem Inkrementieren) erstellt. Gibt es eine Möglichkeit, um sicherzustellen, dass dies wirksam wird, nachdem das Gradle-Skript die Versionsnummer erhöht hat?
Guy
1
@ Guy Entschuldigung, es hat so lange gedauert. Ich habe die Antwort bearbeitet, um zu sehen, ob sie Ihr Problem lösen kann.
Wesley
17

Wenn Sie im defaultConfig-Block keinen Versionsnamen angeben, defaultConfig.versionNameführt dies zunull

Um den Versionsnamen aus dem Manifest zu erhalten, können Sie folgenden Code in build.gradle schreiben:

import com.android.builder.DefaultManifestParser

def manifestParser = new DefaultManifestParser()
println manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile)
Arkadiusz Konior
quelle
7
Ich glaube, dass es mit späteren Versionen von gradle jetzt com.android.builder.core.DefaultManifestParser
Ryan S
8

In meinem Fall wollte ich nur einen Weg finden, um die Generierung verschiedener apkNamen releaseund debugVarianten zu automatisieren . Ich habe es leicht geschafft, indem ich dieses Snippet als Kind von 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)
    }
}

Für das neue Android Gradle Plugin 3.0.0 können Sie so etwas tun:

 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
    }
}

Dies erzeugt so etwas wie: My_nice_name_3.2.31_dbg.apk

Yshahak
quelle
6

Eine andere Alternative ist die Verwendung der folgenden:

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
}

Dadurch wird "appname-1.0.0" für alle Ihre apk-Ausgaben festgelegt.

Marco RS
quelle
Sorry funktioniert nicht mehr (mehr): No such property: archivesBaseName for class: org.gradle.api.internal.project.DefaultProject_Decorated
Martin
Welche Gradle-Version verwenden Sie?
Marco RS
6

Gradle 6+

Ich verwende jetzt Folgendes in Android Studio 4.0 und Gradle 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"
                }
            }
        }
    }
}

Gradle 4

Die Syntax hat sich in Gradle 4 (Android Studio 3+) etwas geändert (von output.outputFilebis outputFileName, Idee aus dieser Antwort ist jetzt:

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def newName = outputFileName
            newName.replace(".apk", "-${variant.versionName}.apk")
            outputFileName = new File(newName)
        }
    }
}
PHPirate
quelle
Irgendeine Idee, wie man das für Gradle 6 behebt?
Spartygw
@spartygw Die Antwort wurde aktualisiert
PHPirate
5

Der richtige Weg, um apk gemäß @ Jon Antwort umzubenennen

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')}"
    }   

Oder auf andere Weise können Sie dieselben Ergebnisse erzielen

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"
        }
    }
}
Qamar
quelle
Schön dazu! Ich mag das besser als andere Arten, wie ich das derzeit mache.
Droid Chris
3

Es gibt viele Antworten, die entweder vollständig oder nach einigen Änderungen richtig sind. Aber ich werde meine trotzdem hinzufügen, da ich das Problem mit allen hatte, weil ich Skripte verwendet habe, um VersionName und VersionCode dynamisch zu generieren, indem ich mich in die eingebunden habepreBuild Aufgabe .

Wenn Sie einen ähnlichen Ansatz verwenden, ist dies der Code, der funktioniert:

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"))
        }
    }
}

Zur Erklärung: Da ich Versionscode und Namen in der ersten Aktion von überschreibe preBuild ich die Umbenennung der Datei am Ende dieser Aufgabe hinzufügen. Was Gradle in diesem Fall tun wird, ist:

Versionscode / Name einfügen-> PreBuild-Aktionen ausführen -> Name für apk ersetzen

Igor Čordaš
quelle
Wo legen Sie die generierten Variablen versionCode und versionName fest?
Mars
Soweit ich mich erinnere, wurde dies in unserem benutzerdefinierten Gradle-Plugin durchgeführt. Seine Ausführung wurde als letzte Aktion der PreBuild-Task aufgerufen.
Igor Čordaš
2
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            output.outputFileName = output.outputFileName.replace(".apk", "-${variant.versionName}.apk")
        }
    }
Zeit läuft
quelle
Während dieses Code-Snippet die Frage lösen kann, hilft eine Erklärung wirklich, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage für Leser in Zukunft beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen.
Rosário Pereira Fernandes
1

In meinem Fall löse ich diesen Fehler auf diese Weise

Hinzufügen eines SUFFIX zur Debug-Version. In diesem Fall füge ich den Text "-DEBUG" zu meiner Debug-Bereitstellung hinzu

 buildTypes {
        release {

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


        }
        debug {

            defaultConfig {
                debuggable true

                versionNameSuffix "-DEBUG"
            }
        }
    }
exequielc
quelle
Der APK-Dateiname wird dadurch nicht geändert.
Tom
1
Das ist eigentlich ein schöner Tipp. Nicht in der richtigen Frage, aber gut. Wo kann ich mehr darüber lesen? Ist es möglich, versionNameSuffixbasierend auf dem GIT-Zweig zu verwenden? Zum Beispiel, wenn es nicht auf "Master" ist, haben Sie immer ein Suffix, auch wenn es eine Release-Version ist
Android-Entwickler
0

Für die neuesten Gradle-Versionen können Sie das folgende Snippet verwenden:

Legen Sie zuerst den Speicherort Ihres Anwendungsmanifests fest

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

Und später 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"))
    }
}

Passen Sie an, ob Sie unterschiedliche Builds pro Build-Typ haben. aber da ich die einzige habe - funktioniert perfekt für mich.

Alfishe
quelle
Ist es möglich, einen String aus einer Klassendatei zum Apk-Namen hinzuzufügen?
Upendra Shah
0

Ab Android Studio 1.1.0 fand ich, dass diese Kombination im Android- Body der build.gradleDatei funktioniert . Dies ist der Fall, wenn Sie nicht herausfinden können, wie die Manifest-XML-Dateidaten importiert werden. Ich wünschte, es würde mehr von Android Studio unterstützt, aber spielen Sie einfach mit den Werten herum, bis Sie die gewünschte Ausgabe des Apk-Namens erhalten:

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"))
                }
            }
        }
    }
A13X
quelle