the studio script plug para now must make for flavors flavor first descargar configurar compile belong available all added android gradle android-gradle

script - Android Studio: Gradle Product Flavors: define propiedades personalizadas



flavors android studio (3)

Estoy creando diferentes versiones de productos de una aplicación de Android en Gradle (Android Studio).

Por eso definí los siguientes sabores de producto:

android { project.ext.set("customer", "") project.ext.set("server", "") //Configuration happens here - code removed for readability buildTypes { debug { server = "test" } release { server = "release" } } //Available product flavors productFlavors { customerA{ customer = "a" } customerB{ customer = "b" } customerC{ customer = "c" } } }

Sin embargo, más adelante, cuando accedo a la propiedad de proyecto definida "cliente" (cuyo valor se establece en el sabor del producto que estoy creando actualmente) en una de mis tareas de compilación, siempre tiene el valor "c", aunque iam construya un clienteA ( en cuyo caso, el cliente de la propiedad debe ser "a" en lugar de "c"). Por ejemplo, ejecuto la siguiente tarea más adelante:

preBuild << { println "Building customer: " + customer }

y siempre se imprime:

Cliente de la construcción: c

¿Entonces estoy adivinando que está sucediendo algo de sobrescritura? ¿Posiblemente relacionado con la configuración de la fase de ejecución VS? No estoy seguro de cómo / por qué, así que cualquier ayuda es muy apreciada.

ACTUALIZACIÓN : Alternativamente, ya me haría llegar más lejos para determinar el nombre del sabor del producto (sin el nombre del tipo de compilación adjunto) y el tipo de compilación (nuevamente: sin el nombre del sabor del producto incluido) durante la fase de ejecución de la compilación gradle .

Teniendo en cuenta la configuración anterior, los nombres de sabor de producto esperados serían: customerA, customerB y customerC.


Durante la fase de evaluación, Gradle ejecuta todo el código en su bloque de android ; no solo ejecuta el código relevante para los sabores que desea compilar. De hecho, durante la fase de evaluación, ni siquiera sabe realmente cuáles son sus sabores; Tiene que evaluar eso para averiguarlo.

Por lo tanto, las tres de sus líneas customer = "a" , customer = "b" y customer = "c" se ejecutarán.

Esta es una de las cosas sutiles de Gradle que hacen que sea un poco difícil de aprender.

Así que he explicado por qué su código no funciona de la manera que espera, pero esta respuesta está incompleta porque no he dicho mucho sobre qué hacer para que funcione correctamente, pero es difícil decir qué hacer porque No estoy seguro de lo que estás tratando de lograr. En general, puedo decir que debería pensar en tratar de lograr lo que desea mediante el uso de tareas definidas por el usuario y configurar dependencias entre tareas para asegurarse de que las cosas se ejecuten en el orden correcto. Un problema con las compilaciones de Android Gradle es que incluso esas tareas no se definen hasta la fase de evaluación (no puede saber qué tareas necesita para compilar todos sus sabores hasta que se evalúa el archivo de compilación y se sabe cuáles son esos sabores). Algunas cosas para ver cómo conectar cosas a las tareas de compilación de Android Gradle: tiene que configurar sus tareas al final de la fase de evaluación después de que el complemento de Android haya hecho su trabajo.


Lo siguiente me sirvió para agregar propiedades personalizadas a los sabores del producto:

android { // ...defaultConfig... productFlavors.whenObjectAdded { flavor -> // Add the property ''myCustomProperty'' to each product flavor and set the default value to ''customPropertyValue'' flavor.ext.set(''myCustomProperty'', ''customPropertyValue'') } productFlavors { flavor1 { } flavor2 { myCustomProperty = ''alternateValue'' } } }

flavor1 tiene el valor predeterminado para la propiedad personalizada, mientras que flavor2 tiene el valor reemplazado.

Aquí hay un ejemplo de cómo acceder a la propiedad personalizada:

applicationVariants.all { variant -> // Get the ''myCustomProperty'' property from the variant''s productFlavor (it''s a list, but there should only be one) def customProp = variant.productFlavors*.myCustomProperty[0] }

Supongo que se podría hacer lo mismo para agregar propiedades personalizadas a los tipos de compilación, pero no he probado esto.


Muchas gracias a Scott Barta, por sus sugerencias y por explicar, por qué mi solución no funcionó (lo que también me hizo reconsiderar algunas cosas). Básicamente se me ocurrieron diferentes maneras de lograr lo que necesitaba.

A menos que no pueda lograrse lo que necesita hacer simplemente organizando su árbol de recursos de Android según los tipos y sabores de compilación (es decir, a través de una convención), entonces recomendaría la opción 2. Aunque conservé la opción 1 para fines de referencia, ya que cubre la Tema interesante de la extensión de la propiedad productFlavor.

  1. Opción personalizada basada en propiedades: Product Flavors le permite definir propiedades personalizadas y así extender un productFlavor. Xavier Ducrohet proporciona un ejemplo aquí: https://.com/a/17708357/1041533

Ofreceré un ejemplo muy simple y similar como se indicó anteriormente, aunque en mi caso necesitaba una propiedad String, en lugar de un booleano.

// This class will be used to create our custom property class StringExtension { String value StringExtension (String value) { this.value = value } public void setValue(String value) { this.value = value } public String getValue() { return value } } android { // Add our new property to each product flavor upon creation productFlavors.whenObjectAdded { flavor -> //I am suspecting the last argument is the default value flavor.extensions.create("myProperty", StringExtension , '''') } // then we can set the value on the extension of any flavor object productFlavors { customerA{ myProperty.value ''customerA'' } customerB{ myProperty.value ''customerB'' } } } //Adds a custom action to the preBuild task preBuild << { //Iterate over all application variants. We name our application variant object "variant" as indicated by "variant ->" android.applicationVariants.all { variant -> //Here we can iterate over the flavors of our variant, well call the flavor "flavor" as indicated by "flavor ->" variant.productFlavors.each { flavor -> //Access our custom property "customerName" println "Building customer" + flavor.customerName.value } } }

Entonces me di cuenta de que lo anterior era totalmente innecesario, porque lo único que quería era el nombre de mi sabor (sin el tipo de compilación) y una vez que encontré la propiedad que me da el nombre de mi sabor, pude cambiar todo. del código anterior como sigue:

  1. Simplemente use el nombre de su sabor como el nombre del cliente accediendo a la propiedad de sabor del producto ya existente llamada "nombre".

    android { productFlavors { customerA{ } customerB{ } } } //Adds a custom action to the preBuild task preBuild << { //Iterate over all application variants. We name our application variant object "variant" as indicated by "variant ->" android.applicationVariants.all { variant -> //Here we can iterate over the flavors of our variant, well call the flavor "flavor" as indicated by "flavor ->" variant.productFlavors.each { flavor -> //Access our product flavor name println "Building customer" + flavor.name } } }

Lo anterior también tiene mucho más sentido, porque mi estructura de directorios para los Recursos de Android lleva el nombre de los sabores reales.

Este último también me llevó a mi solución final para la pregunta original:

  1. Enfoque basado en el directorio de recursos

La intención era modificar un archivo en la carpeta xml de cada cliente en función de si es una versión o una compilación de depuración. Esto se puede lograr mediante una estructura de carpetas correspondiente. Basándonos en la pregunta original, tenemos 3 clientes, y cada cliente tiene una depuración y una versión de lanzamiento. Los archivos xml mencionados anteriormente son diferentes para cada cliente y tipo de compilación. De ahí la siguiente estructura de directorios:

src/ - customerA //Contains all relevant resource files specific to customer A - customerB //Contains all relevant resource files specific to customer B - customerC //Contains all relevant resource files specific to customer C - customerADebug //Contains debug server-settings file for customer A - customerBDebug //Contains debug server-settings file for customer B - customerCDebug //Contains debug server-settings file for customer C - customerARelease //Contains release server-settings file for customer A - customerBRelease //Contains release server-settings file for customer B - customerCRelease //Contains release server-settings file for customer C

Por lo tanto, el contenido principal para cada sabor de producto estaba en la carpeta con el mismo nombre que el sabor (customerA, customerB, etc. vea la primera parte del fragmento de código anterior). Ahora, este archivo, que es diferente en función de si se trata de una compilación de debug o release para cada cliente, se coloca en las carpetas apropiadas, como customerADebug -> contiene un archivo con la configuración del servidor para el modo de depuración, etc.

Y cuando compile customerA, por ejemplo, se elegirá el archivo correcto si crea una depuración o una versión de lanzamiento.

Para responder a la parte de actualización de mi post:

Nombre del sabor del producto (sin buildType):

sabor.nombre (donde el sabor es un sabor de producto)