android - Reemplace los recursos con Gradle dependiendo de buildType
android-studio android-gradle (3)
Debería esforzarse por encontrar una solución que no implique escribir ningún código personalizado en sus archivos de compilación, especialmente el código que hace cosas difíciles con la reasignación de conjuntos de fuentes sobre la marcha. El código personalizado de Gradle es un poco raro de escribir, y es difícil de depurar y mantener. El nuevo sistema de compilación es extremadamente poderoso y ya tiene mucha flexibilidad, y es probable que ya puedas hacer lo que quieras; Es solo una cuestión de aprender cómo.
Especialmente si está aprendiendo los entresijos de los proyectos Android-Gradle (y es tan nuevo que todos lo somos), es mejor esforzarse para trabajar con la funcionalidad incorporada en el sistema antes de pensar fuera de la caja.
Algunas recomendaciones:
- Es poco probable que necesite variar los recursos según el tipo de compilación. Se supone que un tipo de compilación en Android-Gradle es algo como depuración o lanzamiento, donde la diferencia está en la capacidad de depuración, la optimización del compilador o la firma; Se supone que los tipos de construcción son funcionalmente equivalentes entre sí. Si observa las propiedades que puede establecer en un tipo de compilación a través del Groovy DSL , puede ver la intención:
debuggable
,jniDebugBuild
,renderscriptDebugBuild
,renderscriptOptimLevel
,packageNameSuffix
,signingConfig
,zipAlign
,runProguard
,proguardFile
,proguardFiles
. - Si aún crees que quieres variar los recursos según el tipo de compilación, ya existe una forma fácil de hacerlo con el sistema de compilación actual. Puede tener un directorio de recursos específico del tipo de compilación, poner sus recursos allí, y la fusión de recursos en el sistema de compilación se hará cargo de las cosas en el momento de la compilación. Esta es una de las características de gran alcance en Android / Gradle. Consulte Uso de Build Flavors - Estructuración de las carpetas de origen y build.gradle correctamente para obtener información sobre cómo hacer que funcione.
- Si desea variar algo según el tipo de compilación y sus necesidades son muy rápidas y sencillas, es posible que desee cambiar el código de Java en lugar de los recursos y no en el sistema de compilación. Existe el mecanismo
BuildConfig
para ese tipo de cosas: es una clase Java que define un indicadorDEBUG
basado en el estado de compilación de debug / release, y puede agregar su propio código Java personalizado de diferentes tipos de compilación para hacer cosas más significativas.BuildConfig
fue diseñado para permitir pequeñas diferencias funcionales entre los tipos de compilación, para los casos en los que una compilación de depuración podría querer realizar una operación inútil para ayudar en el desarrollo, como realizar una validación de datos más extensa o crear un registro de depuración más detallado, y esas cosas inútiles se optimizan mejor Fuera de las versiones de lanzamiento. Dicho esto, podría ser un mecanismo apropiado para hacer lo que quieras. - Considera usar sabores para lo que estás usando tipos de compilación por ahora. Conceptualmente, un sabor es algo así como un tipo de compilación en el sentido de que es otra variante de su aplicación que puede construirse; el sistema de compilación creará una matriz de sabores frente a tipos de compilación y puede compilar todas las combinaciones. Sin embargo, los sabores abordan un caso de uso diferente, donde los diferentes sabores comparten la mayoría del código, pero pueden tener diferencias funcionales significativas. Un ejemplo común es una versión gratuita vs. paga de su aplicación. Dado que un recurso diferente en diferentes variantes de su aplicación representa una funcionalidad diferente, eso podría indicar la necesidad de un sabor diferente. Los sabores pueden tener diferentes directorios de recursos que se combinan en el momento de la compilación de la misma manera que las configuraciones de compilación; Vea la pregunta vinculada arriba para más información.
Quiero anular algunas cadenas en mi res / strings.xml con gradle.
Sé que desde Android Gradle Plugin 0.7. + Existe la posibilidad de tener una carpeta fuente específica de variante. Pero mi aplicación tiene muchos sabores y no quiero agregar carpetas específicas adicionales a la variante.
ACTUALIZACIÓN 2014-01-17
Lo que quiero en detalle:
Tengo algunas variables en mis Recursos que dependen solo del tipo de construcción (por ejemplo, "release"). Primero pensé que mi SOLUCIÓN_1 (anular los datos después de que los recursos se fusionaran) es agradable, porque si tengo que cambiar estas variables solo tengo que cambiarlas en el build.config (solo un lugar). Pero como Scott Barta escribió en el comentario a continuación, hay algunas buenas razones por las que esta solución NO es una buena idea.
Así que probé otra solución SOLUTION_2 (simplemente fusionando los recursos correctos) basada en este proyecto GitHub de shakalaca . ¡Creo que esta forma es más elegante y todavía tengo la ventaja de cambiar las variables en un solo lugar!
SOLUCIÓN_1 (anular los datos después de fusionar los recursos):
Lo que hice en AS 0.4.2:
en
build.gradle
trato de reemplazar la cadena "Hello World" a "OVERRIDE" ( basado en mi respuesta en esta publicación ):android.applicationVariants.all{ variant -> // override data in resource after merge task variant.processResources.doLast { overrideDataInResources(variant) } } def overrideDataInResources(buildVariant){ copy { // *** SET COPY PATHS *** try { from("${buildDir}/res/all/${buildVariant.dirName}") { // println "... FROM: ${buildDir}/res/all/${buildVariant.dirName}" include "values/values.xml" } } catch (e) { println "... EXCEPTION: " + e } into("${buildDir}/res/all/${buildVariant.dirName}/values") // println "... INTO: ${buildDir}/res/all/${buildVariant.dirName}/values" // --- override string "hello_world" filter { String line -> line.replaceAll("<string name=/"hello_world/">Hello world!</string>", "<string name=/"hello_world/">OVERRIDE</string>"); } // *** SET PATH TO NEW RES *** buildVariant.processResources.resDir = file("${buildDir}/res/all/${buildVariant.dirName}/values/values/values.xml") // println "... NEW RES PATH: " + "${buildDir}/res/all/${buildVariant.dirName}/values/values/values.xml" } }
La tarea de copiar y filtrar funciona bien, pero no pude establecer el valor "nuevo" values.xml como un recurso de cadena.
SOLUCIÓN_2 (simplemente fusionar los recursos correctos)
- definir un floavor para buildType específico (por ejemplo, "releaseRes")
fusiona estos recursos con el sabor que quieres construir:
android.applicationVariants.all{ variant -> variant.mergeResources.doFirst{ checkResourceFolder(variant) } } def checkResourceFolder(variant){ def name = variant.name; if(name.contains("Release")){ android.sourceSets.release.res.srcDirs = [''src/releaseRes/res''] android.sourceSets.flavor1.res.srcDirs = [''src/flavor1/res''] } }
No creo que necesites personalizar el script de compilación para lograr lo que quieres. De acuerdo con mi lectura de http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants ; cuando se ejecute la compilación, los recursos se fusionarán desde las siguientes carpetas, si existen;
src/[flavour][buildType]/res
src/[buildType]/res
src/[flavour]/res
src/main/res
Así que creo que puedes lograr lo que quieres simplemente agregando los recursos en src / release / res.
Aunque puede modificar los nombres de las carpetas especificando los SourceSets relevantes. [Type] .res.srcDirs si realmente desea cambiarlos.
Si alguien se topa con esto
buildTypes {
debug{
buildConfigField "String", "Your_string_key", ''"yourkeyvalue"''
buildConfigField "String", "SOCKET_URL", ''"some text"''
buildConfigField "Boolean", "LOG", ''true''
}
release {
buildConfigField "String", "Your_string_key", ''"release text"''
buildConfigField "String", "SOCKET_URL", ''"release text"''
buildConfigField "Boolean", "LOG", ''false''
}
}
Y para acceder a esos valores utilizando variantes de compilación:
if(!BuildConfig.LOG)
// do something with the boolean value
O
view.setText(BuildConfig.yourkeyvalue);