Intereting Posts
Как обновить содержимое ViewPager? IN и заполнители Android: Как установить слушателя в MenuButton? Как скрыть элементы управления в VideoView в Android? Как настроить таргетинг на различные архитектуры Android? Как масштабировать спрайты в libgdx в соответствии с разрешениями экрана? Android Studio: как удалить APK (или выполнить команду adb) автоматически до запуска или отладки? Кто-нибудь знает, что вызывает «Имя пакета не является допустимым именем пакета» при добавлении нового макета? Android: снимать снимок камеры без подтверждения «сохранить» / «удалить» Как получить разделители в меню NavigationView без заголовков? Как отключить отображение «предложений» на Soft Keyboard Ссылка на веб-страницу для открытия приложения instagram InApp Purchase RESTORE_TRANSACTIONS, я не могу вычислить код Вернуть все столбцы таблицы SQLite в Android Как сделать представление заполнить пространство, доступное для него?

Копирование файла APK в проекте Android Gradle

Я пытаюсь добавить настраиваемую задачу в build.gradle для моего Android, чтобы скопировать окончательный файл APK и Proguard map.txt в другой каталог. Моя задача зависит от задачи assembleDevDebug :

 task publish(dependsOn: 'assembleDevDebug') << { description 'Copies the final APK to the release directory.' ... } 

Я могу посмотреть, как сделать копию файла, используя стандартный тип задачи Copy , согласно документам:

 task(copy, type: Copy) { from(file('srcDir')) into(buildDir) } 

Но предполагается, что вы знаете имя и расположение файла, который хотите скопировать.

Как я могу найти точное имя и расположение файла APK, который был создан как часть задачи assembleDevDebug ? Является ли это доступным как свойство? Мне кажется, что я могу объявить файлы в качестве исходных данных для моей задачи и объявить их как выходы из задачи assemble , но мой Gradle-fu недостаточно силен.

У меня есть специальная логика для ввода номера версии в имя файла APK, поэтому моя задача publish не может просто предполагать имя и местоположение по умолчанию.

Solutions Collecting From Web of "Копирование файла APK в проекте Android Gradle"

Если вы можете получить объект-вариант, связанный с devDebug, вы можете запросить его с помощью getOutputFile ().

Поэтому, если вы хотите опубликовать все варианты, вам будет примерно так:

 def publish = project.tasks.create("publishAll") android.applicationVariants.all { variant -> def task = project.tasks.create("publish${variant.name}Apk", Copy) task.from(variant.outputFile) task.into(buildDir) task.dependsOn variant.assemble publish.dependsOn task } 

Теперь вы можете вызвать gradle publishAll и он опубликует все ваши варианты.

Одна из проблем с файлом сопоставления заключается в том, что задача Proguard не дает вам доступ к местоположению файла, поэтому вы не можете в настоящее время запросить его. Я надеюсь, что это исправится.

Следующий код – это то, что я использую для архивирования сопоставления apk и proguard в zip-файле для каждого варианта с типом сборки «release»:

 def releasePath = file("${rootDir}/archive/${project.name}") def releaseTask = tasks.create(name: 'release') { group 'Build' description "Assembles and archives all Release builds" } android.applicationVariants.all { variant -> if (variant.buildType.name == 'release') { def build = variant.name.capitalize() def releaseBuildTask = tasks.create(name: "release${build}", type: Zip) { group 'Build' description "Assembles and archives apk and its proguard mapping for the $build build" destinationDir releasePath baseName variant.packageName if (!variant.buildType.packageNameSuffix) { appendix variant.buildType.name } if (variant.versionName) { version "${variant.versionName}_${variant.versionCode}" } else { version "$variant.versionCode" } def archiveBaseName = archiveName.replaceFirst(/\.${extension}$/, '') from(variant.outputFile.path) { rename '.*', "${archiveBaseName}.apk" } if (variant.buildType.runProguard) { from(variant.processResources.proguardOutputFile.parent) { include 'mapping.txt' rename '(.*)', "${archiveBaseName}-proguard_\$1" } } } releaseBuildTask.dependsOn variant.assemble variant.productFlavors.each { flavor -> def flavorName = flavor.name.capitalize() def releaseFlavorTaskName = "release${flavorName}" def releaseFlavorTask if (tasks.findByName(releaseFlavorTaskName)) { releaseFlavorTask = tasks[releaseFlavorTaskName] } else { releaseFlavorTask = tasks.create(name: releaseFlavorTaskName) { group 'Build' description "Assembles and archives all Release builds for flavor $flavorName" } releaseTask.dependsOn releaseFlavorTask } releaseFlavorTask.dependsOn releaseBuildTask } } } 

Он создает такие задачи, как:

  • Release – собирает и архивирует все сборки релизов
  • ReleaseFree – собирает и архивирует все версии релизов для аромата Бесплатно
  • ReleaseFreeRelease – сборки и архивы apk и его отображение proguard для сборки FreeRelease
  • ReleasePaid – собирает и архивирует все выпуски для аромата Paid
  • ReleasePaidRelease – сборки и архивы apk и их сопоставление proguard для сборки PaidRelease

Содержимое архива / projectName / packageName-buildType-versionName_versionCode.zip будет:

  • PACKAGENAME-buildType-versionName_versionCode.apk
  • PACKAGENAME-buildType-versionName_versionCode-proguard_mapping.txt

Вот как я копирую файл mappings.txt всякий раз, когда выполняется proguard

 tasks.whenTaskAdded { task -> if (task.name.startsWith("proguard")) {//copy proguard mappings task << { copy { from buildDir.getPath() + "/proguard" into '../proguard' include '**/mapping.txt' } println "PROGUARD FILES COPIED" } } } 

У меня есть несколько хороших указателей здесь, но мне тоже было трудно сделать, как я хотел. Вот моя окончательная версия:

 def archiveBuildTypes = ["distribute"]; def archiveFlavors = ["googleplay"] android.applicationVariants.all { variant -> if (variant.buildType.name in archiveBuildTypes) { variant.productFlavors.each { flavor -> if (flavor.name in archiveFlavors) { def taskSuffix = variant.name.capitalize() def version = "${android.defaultConfig.versionCode} (${android.defaultConfig.versionName})" // assumes that versionName was especified here instead of AndroidManifest.xml def destination = "${rootDir}/${project.name}/archive/${version}" def assembleTaskName = "assemble${taskSuffix}" if (tasks.findByName(assembleTaskName)) { def copyAPKTask = tasks.create(name: "archive${taskSuffix}", type:org.gradle.api.tasks.Copy) { description "Archive/copy APK and mappings.txt to a versioned folder." from ("${buildDir}") { include "**/proguard/${flavor.name}/${variant.buildType.name}/mapping.txt" include "**/apk/${variant.outputFile.name}" } into destination eachFile { file-> file.path = file.name // so we have a "flat" copy } includeEmptyDirs = false } tasks[assembleTaskName].finalizedBy = [copyAPKTask] } } } } } 
 def publish = project.tasks.create("publishAll")// publish all task applicationVariants.all { variant -> if (variant.buildType.name.equals("release")) {// Only Release File outDir = file("//192.168.4.11/Android/Release") File apkFile = variant.outputs[0].outputFile File mapFile = variant.mappingFile def task = project.tasks.create("publish${variant.name.capitalize()}Apk", Copy) task.from apkFile, mapFile task.into outDir task.rename "mapping.txt", "${apkFile.name.substring(0, apkFile.name.length() - 3)}mapping.txt"// Rename mapping.txt task.doLast{ println ">>>publish ${variant.name} success!" + "\ndir: ${outDir}" + "\napk: ${apkFile.name}" } task.dependsOn variant.assemble publish.dependsOn task } } 

Обычно плагин android помещает apks в каталог APP / build / apk.

Итак, запустите assembleDebug затем ls APP/build/apk и вы увидите:

  • APP-отладки unaligned.apk
  • APP-релиз-unaligned.apk
  • APP-релиз-unsigned.apk
  • APP-release.apk и т. Д.