Bagaimana cara mengatur versionName di nama file APK menggunakan gradle?

169

Saya mencoba untuk menetapkan nomor versi tertentu dalam nama file APK yang dihasilkan secara otomatis gradle.

Sekarang gradle menghasilkan myapp-release.apktetapi saya ingin itu terlihat seperti myapp-release-1.0.apk.

Saya telah mencoba mengubah nama opsi yang tampak berantakan. Apakah ada cara sederhana untuk melakukan hal ini?

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

Saya sudah mencoba kode di atas tanpa hasil. Ada saran? (menggunakan gradle 1.6)

codaR0y
sumber

Jawaban:

225

Saya hanya perlu mengubah nama versi di satu tempat. Kode juga sederhana.

Contoh di bawah ini akan membuat file apk bernama MyCompany-MyAppName-1.4.8-debug.apk atau MyCompany-MyAppName-1.4.8-release.apk tergantung pada varian build yang dipilih.

Perhatikan bahwa solusi ini berfungsi pada APK dan Bundel Aplikasi (file .aab) .

Lihat Juga: Cara mengubah nama file pemetaan proguard dalam gradle untuk proyek Android

Solusi untuk Plugin Gradle Terbaru

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

Solusi di atas telah diuji dengan Versi Plugin Android Gradle berikut:

  • 3.5.2 (November 2019)
  • 3.3.0 (Januari 2019)
  • 3.1.0 (Maret 2018)
  • 3.0.1 (November 2017)
  • 3.0.0 (Oktober 2017)
  • 2.3.2 (Mei 2017)
  • 2.3.1 (April 2017)
  • 2.3.0 (Februari 2017)
  • 2.2.3 (Desember 2016)
  • 2.2.2
  • 2.2.0 (September 2016)
  • 2.1.3 (Agustus 2016)
  • 2.1.2
  • 2.0.0 (April 2016)
  • 1.5.0 (2015/11/12)
  • 1.4.0-beta6 (2015/10/05)
  • 1.3.1 (2015/08/11)

Saya akan memperbarui posting ini ketika versi baru keluar.

Solusi Diuji Hanya pada versi 1.1.3-1.3.0

Solusi berikut telah diuji dengan Versi Plugin Android Gradle berikut:

file app gradle:

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
sumber
11
Saya pikir ini adalah pendekatan yang tepat daripada menulis tugas lain untuk mengganti nama file.
Nandish A
5
ubah saja ke archivesBaseName = "MyCompany-MyAppName- $ versionName" jika Anda memiliki OCD dan tidak ingin SAYA memperingatkan Anda tentang +
ligi
4
Great ditemukan, tetapi tidak bekerja dengan baik dengan citarasa dengan kode versi yang berbeda. Mereka semua berakhir dengan kode versi yang sama.
barat
2
Apakah ada cara untuk menambahkan variant.buildType.namenama? Saya tahu ini tidak benar-benar terkait konfigurasi default, tapi saya mencoba mencari cara untuk menghapus variantOutput.getAssemble()peringatan yang sudah usang
Allan W
2
Apakah mungkin menghapus dari nama apk last '-debug' / '-release'?
ilyamuromets
173

Ini memecahkan masalah saya: menggunakan applicationVariants.allbukanapplicationVariants.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")) 
        }
    }       
}

Memperbarui:

Jadi sepertinya ini tidak bekerja dengan versi 0.14+ dari plugin android studio gradle.

Ini caranya (Referensi dari pertanyaan ini ):

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    output.outputFile.parent,
                    output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
        }
    }
}
codaR0y
sumber
3
Apakah Anda tahu bagaimana untuk membuatnya bekerja jika saya telah sebuah versionNamedidefinisikan dalam AndroidManifest.xmlbukannya config Gradle? Itu memberi saya myapp-release-null.apksekarang.
Iwo Banas
1
Jawaban ini tidak berfungsi dengan versi 0.14+ dari plugin gradle. Adakah pembaruan untuk bekerja dengannya?
Argyle
1
@withoutclass Saya menanyakan ini sebagai pertanyaannya sendiri dan menjawabnya di sini: stackoverflow.com/questions/27068505/…
Argyle
2
Untuk orang yang memperbarui ke Gradle 4: ubah eachke alldan output.outputFileke outputFileName. Jika seseorang mengonfigurasi ini berfungsi, itu dapat diedit menjadi jawabannya :)
PHPirate
6
@PHPirate: hampir berfungsi:Error:(34, 0) Cannot set the value of read-only property 'name'
Mooing Duck
47

(Diedit untuk bekerja dengan Android Studio 3.0 dan Gradle 4)

Saya sedang mencari opsi penggantian nama file apk apk lebih kompleks dan saya menulis yang satu ini dengan harapan itu membantu bagi orang lain. Itu mengubah nama apk dengan data berikut:

  • rasa
  • tipe bangunan
  • Versi: kapan
  • tanggal

Saya perlu sedikit riset di kelas gradle dan sedikit copy / paste dari jawaban lain. Saya menggunakan gradle 3.1.3 .

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

Jika Anda mengompilasi hari ini (13-10-2016) pada 10:47, Anda mendapatkan nama file berikut tergantung pada rasa dan tipe bangunan yang Anda pilih:

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

Catatan: nama apk versi yang tidak selaras masih merupakan nama standar.

Fer
sumber
Solusi bagus Saya mencobanya, dan itu sempurna untuk masalah saya. Terima kasih!
Pabel
apakah mungkin menggunakan pendekatan yang sama di Xamarin Studio?
Alessandro Caliaro
Akan lebih bagus jika itu mungkin, tetapi saya mulai sekarang kursus Xamarin dan saya masih belum cukup berlatih untuk mengetahui apakah itu mungkin atau tidak. Saya akan menanyakan pertanyaan ini dan datang ke sini lagi.
Fer
Komentar dari guru kursus: "ada opsi di mana Anda dapat menggunakan perintah untuk mengubah nama file yang dihasilkan". Karenanya, pendekatan yang digunakan dari Xamarin harus berbeda dengan yang saya tulis untuk Android Studio, maaf.
Fer
3
Untuk mengatasi kesalahan Tidak dapat menetapkan nilai dari read-only properti 'OutputFile' - seperti disebutkan dalam komentar sebelumnya karena harus "perubahan eachuntuk alldan output.outputFileuntuk outputFileName" - posting ini menyediakan beberapa rincian tentang bahwa: stackoverflow.com/a/44265374/2162226
Gene Bo
19

Singkatnya, bagi mereka yang tidak tahu cara mengimpor paket build.gradle(seperti saya), gunakan yang berikut 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")) 
        }
    }       
}

===== EDIT =====

Jika Anda mengatur versionCodedan versionNamedalam build.gradlefile Anda seperti ini:

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

Anda harus mengaturnya seperti ini:

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


====== EDIT dengan Android Studio 1.0 ======

Jika Anda menggunakan Android Studio 1.0, Anda akan mendapatkan kesalahan seperti ini:

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

Anda harus mengubah build.Typesbagian ini:

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
sumber
Ini sangat bagus. Namun, karena saya menambah versi manifes saya dalam gradle build, itu akan membuat APK dengan nilai yang lebih lama (pra-kenaikan). Adakah cara untuk memastikan ini terjadi setelah skrip gradle menambah nomor versi?
Guy
1
@ Beli Maaf butuh waktu lama. Saya mengedit jawabannya, lihat apakah itu dapat menyelesaikan masalah Anda.
Wesley
17

Jika Anda tidak menentukan versiName di blok defaultConfig maka defaultConfig.versionNameakan menghasilkannull

untuk mendapatkan versiName dari manifes Anda dapat menulis kode berikut di build.gradle:

import com.android.builder.DefaultManifestParser

def manifestParser = new DefaultManifestParser()
println manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile)
Arkadiusz Konior
sumber
7
Saya percaya bahwa dengan versi gradle yang lebih baru, sekarang adalah com.android.builder.core.DefaultManifestParser
Ryan S
8

Dalam kasus saya, saya hanya ingin menemukan cara untuk mengotomatisasi generasi apknama releasedan debugvarian yang berbeda. Saya berhasil melakukan ini dengan mudah dengan menempatkan cuplikan ini sebagai anak dari 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)
    }
}

Untuk plugin Android gradle 3.0.0 baru Anda dapat melakukan sesuatu seperti itu:

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

Ini menghasilkan sesuatu seperti: My_nice_name_3.2.31_dbg.apk

yshahak
sumber
6

Alternatif lain adalah menggunakan yang berikut ini:

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
}

Ini akan mengatur "appname-1.0.0" untuk semua output apk Anda.

Marco RS
sumber
Maaf tidak berfungsi (lebih lama): No such property: archivesBaseName for class: org.gradle.api.internal.project.DefaultProject_Decorated
Martin
Versi gradle apa yang Anda gunakan?
Marco RS
6

Gradle 6+

Saya sekarang menggunakan yang berikut ini di Android Studio 4.0 dan 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

Sintaks telah berubah sedikit dalam Gradle 4 (Android Studio 3+) (dari output.outputFilemenjadi outputFileName, ide dari jawaban ini sekarang:

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def newName = outputFileName
            newName.replace(".apk", "-${variant.versionName}.apk")
            outputFileName = new File(newName)
        }
    }
}
PHPirate
sumber
Ada yang tahu bagaimana cara memperbaikinya untuk kelas 6?
spartygw
@spartygw Memperbarui jawabannya
PHPirate
5

Cara yang benar untuk mengganti nama apk, sesuai @Jon menjawab

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

Atau cara lain Anda dapat mencapai hasil yang sama dengan

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
sumber
Bagus tentang ini! Saya suka ini lebih baik daripada cara lain yang saya lakukan saat ini.
Droid Chris
3

Ada banyak jawaban yang benar baik secara penuh atau setelah beberapa modifikasi. Tapi saya akan menambahkan milik saya karena saya mempunyai masalah dengan semuanya karena saya menggunakan skrip untuk menghasilkan VersionName dan VersionCode secara dinamis dengan menghubungkan kepreBuild tugas.

Jika Anda menggunakan beberapa pendekatan serupa, ini adalah kode yang akan berfungsi:

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

Untuk menjelaskan: Karena saya mengganti kode dan nama versi dalam tindakan pertama preBuild mengganti saya harus menambahkan pengubahan nama file di akhir tugas ini. Jadi apa yang akan dilakukan gradle dalam kasus ini adalah:

Suntikkan kode versi / nama-> lakukan tindakan preBuild -> ganti nama untuk apk

Igor Čordaš
sumber
Di mana Anda mengatur variabel versionCode dan versiName yang dihasilkan?
Mars
Seingat saya itu dilakukan di dalam plugin gradle kustom kami. Eksekusi disebut sebagai tindakan terakhir dari tugas preBuild.
Igor Čordaš
2
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            output.outputFileName = output.outputFileName.replace(".apk", "-${variant.versionName}.apk")
        }
    }
timeon
sumber
Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda.
Rosário Pereira Fernandes
1

Dalam kasus saya, saya memecahkan kesalahan ini dengan cara ini

menambahkan SUFFIX ke versi Debug, dalam hal ini saya menambahkan teks "-DEBUG" ke penerapan Debug saya

 buildTypes {
        release {

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


        }
        debug {

            defaultConfig {
                debuggable true

                versionNameSuffix "-DEBUG"
            }
        }
    }
exequielc
sumber
Ini tidak mengubah nama file APK.
Tom
1
Ini tip yang bagus, sebenarnya. Bukan dalam pertanyaan yang tepat, tapi bagus. Di mana saya bisa membaca lebih lanjut tentang itu? Apakah mungkin untuk menggunakan versionNameSuffixberdasarkan cabang GIT? Misalnya, jika ini bukan pada "master", selalu memiliki akhiran, bahkan jika itu adalah versi rilis
pengembang android
0

Untuk versi gradle terbaru, Anda dapat menggunakan cuplikan berikut:

Tetapkan lokasi manifes aplikasi Anda terlebih dahulu

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

Dan kemudian di 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"))
    }
}

Sesuaikan jika Anda memiliki manifes berbeda untuk setiap tipe bangunan. tapi karena saya punya satu - bekerja dengan baik untuk saya.

Alfishe
sumber
apakah mungkin menambahkan string dari file kelas ke nama apk ??
Upendra Shah
0

Pada Android Studio 1.1.0, saya menemukan kombinasi ini berfungsi di tubuh androidbuild.gradle file. Ini jika Anda tidak tahu cara mengimpor data file manifes xml. Saya berharap ini lebih didukung oleh Android Studio, tetapi hanya bermain-main dengan nilai-nilai sampai Anda mendapatkan output nama apk yang diinginkan:

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
sumber