Android Studio Gradle с указанием выходного каталога, специфичного для Flavor
Я реализовал Flavors в Android Studio и сейчас пытаюсь поместить каждый Flavor в отдельный каталог со своим уникальным именем - к сожалению, с именем, которое в некоторых случаях отличается от имени аромата.:(
У нас есть инструменты, в зависимости от того, что это одно и то же, так что, если я справлюсь с этим в Gradle, тем лучше.
У меня есть пример, который использует значение суффикса имени версии в качестве имени каталога, и это работает. Но то, что я хотел бы сделать, это указать значение где-то в конфигурации флейвора, которое будет использоваться, однако я обнаружил, что когда вы устанавливаете свойство с тем же именем, выигрывает последнее, а не каждое из них используется, как указано в конфиге.
Например, допустим, у меня есть два вкуса: Джимбо и Рэндольф. Однако я хочу поместить Jimbo.apk в папку "jimmy" и Randolph.apk в папку "randy". Как я могу указать значение (каталог) для каждого, который будет выбран и использован для хранения сгенерированного APK? Чтобы добавить к сложности, я переименую текущий APK в applicationVariants.all
,
В приведенном ниже коде я ищу как-то заменить versionNameSuffix
с переменной могу как-то уточнить.
Вот что у меня есть:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
defaultConfig {
applicationId "com.mycompany.default"
minSdkVersion 14
targetSdkVersion 23
versionCode 11
versionName "1.0.11"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
signingConfig signingConfigs.config
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
productFlavors {
Randolph {
applicationId 'com.mycompany.randy'
versionNameSuffix 'randy'
}
Jimbo {
applicationId 'com.mycompany.jimmy'
versionNameSuffix 'jimmy'
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def path = "C:/AndroidBuilds/MyCompany.Build/" + variant.productFlavors[0].versionNameSuffix + "/"
logger.error("Path = " + path)
def SEP = "-"
def flavor = variant.productFlavors[0].name
def version = variant.versionCode
def newApkName = path + version + SEP + flavor
logger.error("newApkName = " + newApkName)
output.outputFile = new File(newApkName + ".apk")
}
}
}
dependencies {
}
}
ОБНОВИТЬ
На вопрос об использовании задачи, я попробовал этот подход, но проблема установки каталога остается - с помощью свойства (archivesBaseName
) используется последний набор, поэтому все файлы копируются в этот каталог. Вот образец этого. Поскольку у меня есть более 100 вариантов для создания, я хочу, чтобы каждый отправлялся в свой собственный каталог и управлял конфигурацией. Вот что я попробовал:
productFlavors {
Randolph {
applicationId 'com.mycompany.randy'
setProperty("archivesBaseName", "randy")
}
Jimbo {
applicationId 'com.mycompany.jimmy'
setProperty("archivesBaseName", "jimmy")
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def path = "C:/AndroidBuilds/MyCompany.Build/" + archivesBaseName + "/"
logger.error("Path = " + path)
def SEP = "-"
def flavor = variant.productFlavors[0].name
def version = variant.versionCode
def newApkName = path + version + SEP + flavor
logger.error("newApkName = " + newApkName)
output.outputFile = new File(newApkName + ".apk")
def copyApkTask = tasks.create(name: "copy" + variant.name + "Apk") {
copy {
def newName = newApkName + ".apk"
logger.error("from = " + newName)
logger.error("into = " + path)
logger.error("old name = " + version + SEP + flavor + ".apk")
logger.error("new name = " + flavor + ".apk")
from newName
into path
rename (version + SEP + flavor + ".apk", flavor + ".apk")
}
}
copyApkTask.mustRunAfter variant.assemble
}
}
В приведенном выше примере я добавил задачу, чтобы дополнительно скопировать APK с другим именем в специфический каталог. Все APK в конечном итоге копируются в последнее указанное значение `archivesBaseName ', которое является"jimmy". Так что последний побеждает. Я надеялся, что это будет действовать как переменная. Я предпочел бы не иметь 100+, если заявления сделать это, и предпочел бы сделать это в Gradle. Я начинаю задумываться, нужно ли мне сделать внешний вызов Ant, чтобы все это работало.
2 ответа
Хорошо, в конце эта конкретная ссылка ДЕЙСТВИТЕЛЬНО помогла при назначении переменной, что мне и было нужно:
Android Studio: варианты продукта Gradle: определение пользовательских свойств
По сути, вы можете назначать переменные внутри аромата. Вот что я в итоге сделал, что на самом деле пошло немного дальше, чем когда я начинал, так как теперь я могу использовать Flavor в качестве имени APK или указать его (я знаю, это испорчено, но история может быть такой!):
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
defaultConfig {
applicationId "com.mycompany.default"
minSdkVersion 14
targetSdkVersion 23
versionCode 11
versionName "1.0.11"
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
signingConfig signingConfigs.config
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
productFlavors.whenObjectAdded { flavor ->
// Add the property 'myCustomProperty' to each product flavor and set the default value to 'customPropertyValue'
flavor.ext.set('directoryPath', '')
flavor.ext.set('apkName', '')
}
productFlavors {
Randolph {
applicationId 'com.mycompany.randy'
directoryPath = 'randy'
apkName = 'RandyBoy' // If you want the APK name be different than the flavor
}
Jimbo {
applicationId 'com.mycompany.jimmy'
directoryPath = 'jimmy'
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def path = "C:/AndroidBuilds/MyCompany.Build/" + variant.productFlavors[0].directoryPath + "/"
def SEP = "-"
def apkName = variant.productFlavors[0].apkName
def flavor = variant.productFlavors[0].name
if (apkName != '')
flavor = apkName;
def version = variant.versionCode
def newApkName = path + version + SEP + flavor
logger.error("newApkName = " + newApkName)
output.outputFile = new File(newApkName + ".apk")
}
}
}
dependencies {
}
}
Так productFlavors.whenObjectAdded
устанавливает значения по умолчанию для каждого аромата, которые затем переопределяются каждым ароматом. в applicationVariants.all
выполняется проверка, чтобы убедиться, что apkName
был переопределен, если это так, он использует его, в противном случае он использует имя аромата (и перед ним добавляется код версии). Каталог устанавливается напрямую по вкусу.
Большое спасибо @lionscribe. Он заставил меня думать об этом более четко.
Проблема в том, что setProperty устанавливает свойство Project, поэтому оно всегда перезаписывается. Простое решение - это использовать дополнительное свойство Varients. Что-то вроде этого.
productFlavors {
Randolph {
applicationId 'com.mycompany.randy'
ext.archivesBaseName = "randy" }
Jimbo {
applicationId 'com.mycompany.jimmy'
ext.archivesBaseName=jimmy" }
}
Тогда вы получите доступ к нему в задаче как
def path = "C:/AndroidBuilds/MyCompany.Build/" + variant.ext.archivesBaseName + "/"
Я не проверял это, и это может быть ошибка, и нужно немного настроить.
Обновить
Этого недостаточно, поскольку Gradle устанавливает свойство ext объекта flavor, только если оно определено в объекте flavour. В противном случае он будет установлен в родительском или корневом объекте, которым является проект. Таким образом, чтобы это работало, мы сначала должны определить свойство в объекте flavour. Это можно сделать так, как @Stephen ответил ниже. Следуйте его проверенному методу.
Есть еще 3 варианта:
1. Используйте разные имена переменных для каждого вкуса, предварительно ожидая имя вкуса, например "Jimbo_archivesBaseName". Затем получите к нему доступ, используя свойство (flavName + "_archivesBaseName);
2. Используйте глобальную переменную HashMap, задав путь для каждого имени разновидности.
3. Использование функции, которая возвращает путь на основе имени аромата.