sourcesets - ¿Cómo reemplazar una cadena para una buildvariant con gradle en android studio?
gradle version android studio (4)
Tengo dos sabores de mi proyecto:
flavor1 -> packagename: com.example.flavor1
flavor2 -> packagename: com.example.flavor2
Ahora quiero construir una variante de construcción de sabor1 y sabor2. La única diferencia de la variante de compilación es otro nombre de paquete.
Mi proyecto usa MapFragments y tiene solo un Manifiesto, así que puse el nombre de permiso de MAPS_RECEIVE en mis archivos de recursos de cadenas de los respectivos sabores.
La pregunta es: ¿cómo puedo reemplazar un recurso de cadena de una variante de construcción?
Probé el siguiente enfoque ( descrito en esta publicación ):
buildTypes{
flavor1Rev{
packageName ''com.example.rev.flavor1''
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [''package_permission'' : ''com.example.rev.flavor1.permission.MAPS_RECEIVE''])
}
}
Pero usando esto obtuve este error:
No se pudo encontrar el método filter () para los argumentos [{tokens = {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, signingConfig = null}] en BuildTypeD sl_Decorated {name = buderusFinal, debuggable = false, jniDebugBuild = false, renderscr iptDebugBuild = false, renderscriptOptimLevel = 3 , packageNameSuffix = null, versionNa meSuffix = null, runProguard = falso, zipAlign = true, signingConfig = null}.
¿Tengo que definir una tarea propia para el método de filtro?
EDIT [2013_07_09]:
Cadena en src / flavor1 / res:
<string name="package_permission">package_permission</string>
Codifique en build.gradle para reemplazar la cadena:
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''
}
}
}
En la actual DSL de Android Gradle, la clase ApplicationVariant
ha cambiado y el enfoque de Saad debe reescribirse, por ejemplo, de la siguiente manera:
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'')
}
El nuevo DSL también ofrece un enfoque más limpio para llegar directamente al archivo de manifiesto.
Las respuestas están bastante desactualizadas, ahora hay mejores formas de archivarlas. Puede usar el comando en su build.gradle:
manifestPlaceholders = [
myPlaceholder: "placeholder",
]
y en tu manifiesto:
android:someManifestAttribute="${myPlaceholder}"
más información se puede encontrar aquí: https://developer.android.com/studio/build/manifest-merge.html
Resolví el problema yo solo, así que aquí está la solución "paso a paso": quizás ayude a otros principiantes a jugar gradle :)
Copiar Tarea en General:
copy{ from("pathToMyFolder"){ include "my.file" } // you have to use a new path for youre modified file into("pathToFolderWhereToCopyMyNewFile") }
Reemplaza una línea en General:
copy { ... filter{ String line -> line.replaceAll("<complete line of regular expression>", "<complete line of modified expression>") } }
Creo que el mayor problema fue obtener los caminos correctos, porque tenía que hacer esto de forma dinámica ( este enlace fue muy útil para mí ). Resolví mi problema reemplazando las líneas especiales en el manifiesto y no en el archivo String.
El siguiente ejemplo muestra cómo reemplazar la etiqueta "metadatos" en el manifiesto para usar google-maps-api-key (en mi caso hay diferentes sabores que usan claves diferentes):
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") } } }
Uso casi exactamente el enfoque que deseabas. El replaceInManfest
también es genérico y se puede usar también para otros marcadores de posición. El método getGMapsKey()
simplemente devuelve la clave adecuada en función de buildType.
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'')
}
También me gist
si quieres ver si evoluciona más tarde.
Encontré que este es un enfoque más elegante y generalizable que los demás (aunque el reemplazo de token simplemente hubiera sido más agradable).