Как заменить строку для buildvariant с помощью gradle в студии Android?
У меня есть два варианта моего проекта:
flavor1 -> packagename: com.example.flavor1
flavor2 -> packagename: com.example.flavor2
Теперь я хочу построить buildvariant вкуса1 и flavor2.
Единственное отличие buildvariant - другое имя пакета.
Мой проект использует MapFragments и имеет только один манифест - поэтому я поместил имя MAPS_RECEIVE в мои файлы с строковыми ресурсами соответствующих ароматов.
Возникает вопрос: как заменить строковый ресурс buildvariant?
Я пробовал следующий подход (описанный в этом сообщении):
buildTypes{
flavor1Rev{
packageName 'com.example.rev.flavor1'
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: ['package_permission' : 'com.example.rev.flavor1.permission.MAPS_RECEIVE'])
}
}
Но используя это, я получил эту ошибку:
Не удалось найти метод filter() для аргументов [{{Лексемы = package_permission = com.example.rev.flavor1.permission.MAPS_RECEIVE}}, BuildTypeDsl_D ecorated {name = ReplaceTokens, debuggable = false, jniDebugBuild = false, renderscript DebugBuild = false, renderscriptOptimLevel = 3, packageNameSuffix = null, versionNameS uffix = null, runProguard = false, zipAlign = true, signedConfig = null}] on BuildTypeD sl_Decorated {name = buderusFinal, debuggable = false, jniDebugBuild = false, renderscr iptDebugBuild = false, renderscriptOptimLevel = 3, packageNameSuffix = null, versionNa meSuffix = null, runProguard = false, zipAlign = true, signedConfig = null}.
Нужно ли определять собственную задачу для метода фильтрации?
EDIT [2013_07_09]:
Строка в src/flavor1/res:
<string name="package_permission">package_permission</string>
Код в build.gradle для замены строки:
buildTypes{
flavor1Rev{
copy{
from('src/res/'){
include '**/*.xml'
filter{String line -> line.replaceAll(package_permission, 'com.example.rev.flavor1.permission.MAPS_RECEIVE')}
}
into '$buildDir/res'
}
}
}
Ответы
Ответ 1
Я решил проблему самостоятельно, так что вот решение "шаг за шагом" - возможно, это поможет некоторым другим новичкам в gradle:)
- Скопировать задачу в целом:
copy{
from("pathToMyFolder"){
include "my.file"
}
// you have to use a new path for youre modified file
into("pathToFolderWhereToCopyMyNewFile")
}
filter{
String line -> line.replaceAll("<complete line of regular expression>",
"<complete line of modified expression>")
}
-
Я думаю, что самая большая проблема заключалась в том, чтобы получить правильные пути, потому что мне приходилось делать это динамически (эта ссылка была очень полезной для меня). Я решил свою проблему, заменив специальные строки в манифесте, а не в String файле.
-
В следующем примере показано, как заменить мета-данные -tag в манифесте, чтобы использовать ваши google-maps-api-key (в моем случае есть разные варианты, которые используют разные ключи):
android.applicationVariants.each{ variant ->
variant.processManifest.doLast{
copy{
from("${buildDir}/manifests"){
include "${variant.dirName}/AndroidManifest.xml"
}
into("${buildDir}/manifests/$variant.name")
// define a variable for your key:
def gmaps_key = "<your-key>"
filter{
String line -> line.replaceAll("<meta-data android:name=\"com.google.android.maps.v2.API_KEY\" android:value=\"\"/>",
"<meta-data android:name=\"com.google.android.maps.v2.API_KEY\" android:value=\"" + gmaps_key + "\"/>")
}
// set the path to the modified Manifest:
variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml")
}
}
}
Ответ 2
Я использую почти тот подход, который вы хотели. replaceInManfest
также является общим и может использоваться и для других заполнителей. Метод getGMapsKey()
просто возвращает соответствующий ключ на основе типа build.
applicationVariants.all { variant ->
def flavor = variant.productFlavors.get(0)
def buildType = variant.buildType
variant.processManifest.doLast {
replaceInManifest(variant,
'GMAPS_KEY',
getGMapsKey(buildType))
}
}
def replaceInManifest(variant, fromString, toString) {
def flavor = variant.productFlavors.get(0)
def buildtype = variant.buildType
def manifestFile = "$buildDir/manifests/${flavor.name}/${buildtype.name}/AndroidManifest.xml"
def updatedContent = new File(manifestFile).getText('UTF-8').replaceAll(fromString, toString)
new File(manifestFile).write(updatedContent, 'UTF-8')
}
У меня есть на gist
, если вы хотите узнать, развивается ли он позже.
Я нашел, что это более элегантный и обобщаемый подход, чем другие (хотя замена токена просто работала бы лучше).
Ответ 3
Ответы довольно устарели, теперь лучше их архивировать. Вы можете использовать команду в файле build.gradle:
manifestPlaceholders = [
myPlaceholder: "placeholder",
]
и в вашем манифесте:
android:someManifestAttribute="${myPlaceholder}"
дополнительную информацию можно найти здесь:
https://developer.android.com/studio/build/manifest-merge.html
Ответ 4
В текущем DSL-телефоне Android Gradle класс ApplicationVariant
изменился, и подход Saad должен быть перезаписан, например. следующим образом:
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.processManifest.doLast {
replaceInManifest(output,
'GMAPS_KEY',
getGmapsKey(buildType))
}
}
}
def replaceInManifest(output, fromString, toString) {
def updatedContent = output.processManifest.manifestOutputFile.getText('UTF-8')
.replaceAll(fromString, toString)
output.processManifest.manifestOutputFile.write(updatedContent, 'UTF-8')
}
Новый DSL также предлагает более чистый подход для непосредственного доступа к файлу манифеста.