Як встановити versionName у назві файлу APK за допомогою gradle?


169

Я намагаюся встановити певний номер версії в імені файлу APK, створеному в Gradle, автоматично створеному.

Тепер Gradle генерує, myapp-release.apkале я хочу, щоб це виглядало як щось схоже myapp-release-1.0.apk.

Я спробував перейменувати варіанти, які здаються безладними. Чи є простий спосіб це зробити?

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

Я спробував код вище, не пощастивши. Будь-які пропозиції? (використовуючи градуле 1.6)

Відповіді:


225

Мені залишається лише змінити назву версії в одному місці. Код теж простий.

Наведені нижче приклади створюватимуть apk-файли з назвою MyCompany-MyAppName-1.4.8-debug.apk або MyCompany-MyAppName-1.4.8-release.apk залежно від обраного варіанту збірки.

Зауважте, що це рішення працює як у пакетах APK, так і в додатках (файлах .aab) .

Дивіться також: Як змінити ім'я файлу прогуардового відображення в gradle для проекту Android

Рішення для недавнього плагіна Gradle

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

Вищевказане рішення було випробувано за допомогою наступних версій плагіна Android Gradle:

  • 3.5.2 (листопад 2019 р.)
  • 3.3.0 (січень 2019)
  • 3.1.0 (березень 2018 року)
  • 3.0.1 (листопад 2017 р.)
  • 3.0.0 (жовтень 2017)
  • 2.3.2 (травень 2017 р.)
  • 2.3.1 (квітень 2017)
  • 2.3.0 (лютий 2017)
  • 2.2.3 (грудень 2016 р.)
  • 2.2.2
  • 2.2.0 (вересень 2016)
  • 2.1.3 (серпень 2016 р.)
  • 2.1.2
  • 2.0.0 (квітень 2016)
  • 1.5.0 (2015/11/12)
  • 1.4.0-beta6 (2015/10/05)
  • 1.3.1 (11.08.2015)

Я оновлю цю посаду, коли вийдуть нові версії.

Рішення випробувано лише у версіях 1.1.3-1.3.0

Наступне рішення було випробувано за допомогою наступних версій плагіна Android Gradle:

файл 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"
    }
}

11
Я думаю, що це правильний підхід, а не писати ще одне завдання для перейменування файлів.
Нандіш А

5
просто змініть на archivesBaseName = "MyCompany-MyAppName- $ versionName", якщо у вас є OCD і не хочете, як попереджати вас про +
ліги

4
Чудова знахідка, але не справляється з ароматами з різними кодами версій. Всі вони закінчуються одним і тим же кодом версії.
weston

2
Чи є якийсь спосіб додати variant.buildType.nameім’я? Я знаю, що це насправді не пов’язано з конфігурацією за замовчуванням, але я намагаюся з’ясувати, як видалити застаріле variantOutput.getAssemble()попередження
Allan W

2
Чи можливо видалити з apk name last '-debug' / '-release'?
ілямуромець

173

Це вирішило мою проблему: використання applicationVariants.allзамістьapplicationVariants.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")) 
        }
    }       
}

Оновлення:

Отож, схоже, це не працює з 0.14+ версіями плагіну для android studio gradle.

Це робить фокус (посилання на це запитання ):

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

3
Чи знаєте ви, як змусити його працювати, якщо у мене versionNameвизначений AndroidManifest.xmlконфігурація замість gradle? Це дає мені myapp-release-null.apkзараз.
Iwo Banas

1
Ця відповідь не працює з 0,14+ версіями плагіна gradle. Будь-які оновлення для роботи з ними?
Argyle

1
@withoutclass Я запитав це як власне запитання і на нього відповів тут: stackoverflow.com/questions/27068505/…
Argyle

2
Для людей, що оновлюються до Gradle 4: перехід eachна allта output.outputFileдо outputFileName. Якщо хтось підтверджує це, це може бути відредаговано у відповідь :)
PHPirate

6
@PHPirate: майже працює:Error:(34, 0) Cannot set the value of read-only property 'name'
Mooing Duck

47

(РЕЄСТАНОВАНО для роботи з Android Studio 3.0 та Gradle 4)

Я шукав більш складний варіант перейменування файлу apk, і написав цей, сподіваючись, що це корисно для всіх інших. Він перейменовує apk із такими даними:

  • аромат
  • тип збірки
  • версія
  • дата

Мені знадобилося трохи досліджень у класах з ґредле та трохи копіювання / вставки з інших відповідей. Я використовую gradle 3.1.3 .

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

Якщо ви збираєте сьогодні (13-10-2016) о 10:47, ви отримаєте такі назви файлів залежно від обраного вами смаку та типу складання:

  • debu debug : myProject_ dev_debug_1.3.6 _131016_1047.apk
  • випуск dev : myProject_ dev_release_1.3.6 _131016_1047.apk
  • prod налагодження : myProject_ prod_debug_1.2.0 _131016_1047.apk
  • випуск prod : myProject_ prod_release_1.2.0 _131016_1047.apk

Примітка: ім'я apk для нерівномірної версії все ще є типовим.


Прекрасне рішення. Я спробував це, і це ідеально підходить для моєї проблеми. Дякую!
Пабель

чи можна використовувати той самий підхід у студії Xamarin?
Алессандро Кальяро

Було б чудово, якби це було можливо, але я зараз починаю курс Xamarin, і я все ще не маю достатньої кількості практики, щоб знати, чи можливо це чи ні. Я задам це питання і прийду сюди ще раз.
Фер

Коментар викладача курсу: "є варіант, коли ви можете використовувати команди для зміни назви створених файлів". Тому підхід до використання від Xamarin повинен відрізнятися від того, який я написав для Android Studio, вибачте.
Фер

3
Для усунення помилки Неможливо встановити значення властивість тільки для читання «OUTPUTFILE» - як уже згадувалося в попередньому коментарі для того , щоб «зміни eachв allі output.outputFileдо outputFileName» - це повідомлення містить деякі подробиці про те, що: stackoverflow.com/a/44265374/2162226
Джин Бо

19

Підводячи підсумок, для тих, хто не знає, як імпортувати пакет build.gradle(як я), використовуйте наступне 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 =====

Якщо ви встановите свій versionCodeі versionNameу своєму build.gradleфайлі так:

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

Ви повинні встановити його так:

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


====== РЕДАКТУЙТЕ з Android Studio 1.0 ======

Якщо ви використовуєте Android Studio 1.0, ви отримаєте помилку на зразок цієї:

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

Ви повинні змінити build.Typesчастину на це:

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

Це чудово працює. Однак, оскільки я збільшив свою маніфестову версію в збірці gradle, вона створить APK зі старшим (до збільшення) значенням. Будь-який спосіб переконатися, що це вплине після збільшення скрипту gradle номер версії?
Хлопець

1
@Guy Вибачте пройшло так багато часу. Я відредагував відповідь, подивіться, чи може вона вирішити вашу проблему.
Веслі

17

Якщо в блоці defaultConfig не вказати versionName, defaultConfig.versionNameце призведе доnull

щоб отримати versionName з маніфесту, ви можете написати наступний код у build.gradle:

import com.android.builder.DefaultManifestParser

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

7
Я вважаю, що з пізнішими версіями gradle, це тепер com.android.builder.core.DefaultManifestParser
Ryan S

8

У моєму випадку я просто хотів знайти спосіб автоматизації генерації різних apkназв для releaseі debugваріантів. Мені вдалося це зробити легко, поставивши цей фрагмент як дитина 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)
    }
}

Для нового плагіна Android gradle 3.0.0 ви можете зробити щось подібне:

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

Це дає щось подібне: My_nice_name_3.2.31_dbg.apk


6

Іншою альтернативою є використання наступного:

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
}

Це встановить "appname-1.0.0" на всі ваші apk виходи.


Вибачте, не працює (більше): No such property: archivesBaseName for class: org.gradle.api.internal.project.DefaultProject_Decorated
Мартін

Яку версію gradle ви використовуєте?
Марко РС

6

Gradle 6+

Зараз я використовую наступне в Android Studio 4.0 та 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"
                }
            }
        }
    }
}

4 градус

Синтаксис трохи змінився в Gradle 4 (Android Студія 3+) (від output.outputFileдо outputFileName, ідея від цієї відповіді зараз:

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

Будь-яка ідея, як це виправити для gradle 6?
spartygw

@spartygw Оновлено відповідь
PHPirate

5

Правильний спосіб перейменувати apk, відповідно до @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')}"
    }   

Або іншим способом можна досягти однакових результатів

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

Гарний на цьому! Мені це подобається краще, ніж інші способи, які я зараз роблю.
Дроїд Кріс

3

Є багато відповідей, які є правильними або повністю, або після деяких модифікацій. Але я все одно додам свою, оскільки у мене виникли проблеми з усіма ними, оскільки я використовував сценарії для динамічного генерування VersionName та VersionCode, підключаючись до preBuildзавдання.

Якщо ви використовуєте якийсь подібний підхід, це код, який буде працювати:

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

Для пояснення: Оскільки я переважаю код версії та ім’я версії в першій дії, preBuildя повинен додати перейменування файлу до кінця цього завдання. Отже, що градель зробить у цьому випадку, це:

Ін'єктуйте код версії / ім'я версії-> виконайте дії preBuild -> замініть ім'я на apk


Де ви встановлюєте згенеровані змінні versionCode та versionName?
Марс

Як я пам'ятаю, це було зроблено всередині нашого користувацького плагіну gradle. Його виконання було названо останньою дією завдання preBuild.
Ігор Чордаш

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

Хоча цей фрагмент коду може вирішити питання, зокрема пояснення дійсно допомагає покращити якість вашої публікації. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду.
Розаріо Перейра Фернандес

1

У моєму випадку я вирішую цю помилку таким чином

додавання SUFFIX до версії налагодження, у цьому випадку я додаю текст "-DEBUG" до мого розгортання налагодження

 buildTypes {
        release {

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


        }
        debug {

            defaultConfig {
                debuggable true

                versionNameSuffix "-DEBUG"
            }
        }
    }

Це не змінює назву файлу APK.
Том

1
Це хороша порада насправді. Не в правильному питанні, але в хорошому. Де я можу прочитати більше про це? Чи можливо використовувати versionNameSuffixна основі гілки GIT? Наприклад, якщо він не на "master", завжди майте суфікс, навіть якщо це версія для випуску
android developer

0

Для останніх версій gradle ви можете використовувати наступний фрагмент:

Спершу встановіть місцезнаходження маніфесту програми

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

А згодом у 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"))
    }
}

Налаштуйте, якщо у вас є різні маніфести на тип збірки. але оскільки у мене є єдиний - для мене прекрасно працює.


чи можна додати рядок із файлу класу до apk name ??
Упендра Шах

0

Що стосується Android Studio 1.1.0, я виявив, що ця комбінація працює в тілі файлу Androidbuild.gradle . Це якщо ви не можете зрозуміти, як імпортувати дані файлів маніфесту XML. Я б хотів, щоб він більше підтримувався Android Studio, але просто пограйте зі значеннями, поки не отримаєте потрібний вихід apk імені:

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"))
                }
            }
        }
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.