Generación dinámica de sabores de productos

He creado una aplicación de Android que debe ser construida en muchos (30 +) sabores.

Mi idea era generar los diferentes productFlavors directamente desde la estructura de carpetas en mi directorio src , ya que la configuración siempre es muy similar (básicamente sólo otro nombre de paquete, un nuevo icono de lanzador y algunas cadenas cambian).

La carpeta src este aspecto:

 └── src ├── flavor1 │  ├── flavor2.keystore │  ├── res ├── flavor2 │  ├── res │  ├── flavor2.keystore └── main  ├── AndroidManifest.xml  ├── java  └── res 

Si tuviera que crear las propiedades gradle a mano se vería de alguna manera como esto:

 android { .... productFlavors { flavor1 { packageName 'com.example.flavor1' } flavor2 { packageName 'com.example.flavor2' } } } 

Cada vez que intento cambiar la configuración de productFlavors después de su creación consigo un error o los cambios / adiciones son ignorados silenciosamente.
Esto podría ser un problema causado por mí, porque mi experiencia de Gradle / Groovy es muy limitada, o esto no es posible.

La mayoría de las GroupableProductFlavorDsl_Decorated obtienes un error, diciendo que GroupableProductFlavorDsl_Decorated no podría ser manipulado de la manera que yo quiera.

Lo que estoy tratando de archivar de alguna manera se vería así:

 android { .... def flavors = getMyFlavorsFromFileSystem() productFlavors { } flavors.each { name, config -> productFlavors[name] << config } } 

Nota: Sé que esta pregunta es básicamente un duplicado de una pregunta anterior, que tristemente nunca fue contestada. Desde Gradle es algo nuevo para el mundo de Android, espero obtener más respuestas como desde la última vez que se hizo la pregunta, porque más desarrolladores están usando Gradle ahora.

Actualizar:

Aquí algunos enfoques muy simples que he intentado:

Variante 1:

 android { productFlavors { } productFlavors['flavor1'] << { packageName "com.example.flavor1" } productFlavors['flavor2'] << { packageName "com.example.flavor2" } } /* A problem occurred evaluating root project 'MyProject'. > GroupableProductFlavorDsl with name 'flavor1' not found. */ 

Variante 2:

 android { productFlavors { } productFlavors['flavor1'] = { packageName "com.example.flavor1" } productFlavors['flavor2'] = { packageName "com.example.flavor2" } } /* no error, but does not work */ 

Variante 3:

 android { productFlavors { } productFlavors['flavor1'] = [packageName: "com.example.flavor1"] productFlavors['flavor2'] = [packageName: "com.example.flavor2"] } /* no error, but does not work */ 

Todos ellos como un Gist .

Resuelto por ensayo y error:

 android { // let's assume these are return by a function which reads the filesystem def myFlavors = [ flavor1: [ packageName: "com.example.flavor1" ], flavor2: [ packageName: "com.example.flavor2" ] ] productFlavors { myFlavors.each { name, config -> "$name" { packageName config.packageName } } } } 

Sé que ya hay una respuesta para esto, pero he combinado el acercamiento de Chris.Zou con TheHippo. Y añadir mi propio método para hacer esto.

Básicamente, cuando se trata de sabores, normalmente trabajamos con diferentes directorios en / app / src / que contiene recursos. Y como el nombre del directorio es igual al nombre del paquete, simplemente enumeré los directorios de esa carpeta (excluidos "main" y "androidTest").

Así que aquí está mi script de gradle completo, que funciona:

 def map = [:] new File("./app/src").eachFile() { file-> def fileName = file.getName() if( fileName == "main" || fileName == "androidTest") { return } map.put(fileName, 'com.mypackagename.' + fileName ) } productFlavors { map.each { flavorName, packagename -> "$flavorName" { applicationId packagename } } } 

Editar:

  • También quisiera agregar, el com.mypackagename es básicamente el path de raíz para todos los sabores.
  • Tengo un script separado que copia-pega el directorio de un sabor a la carpeta / app / src /.

Dado que el autor de la pregunta no quería compartir su código para leer los archivos. Voy a escribir sobre lo que hice. Puse todas las variantes de nombre en un archivo llamado "app / build_variants.txt", una línea para cada uno, algo así:

 flavor1 flavor2 flavor3 flavor4 flavor5 

Y en "app / build.gradle":

 //...other configs... android { productFlavors { new File('app/build_variants.txt').eachLine { "$it" { resValue "string", "build_variant_name", "$it" } } } } //...other configs 

Esto tendrá el mismo resultado que el código siguiente:

 //...other configs... android { productFlavors { flavor1 { resValue "string", "build_variant_name", "flavor1" } flavor2 { resValue "string", "build_variant_name", "flavor2" } flavor3 { resValue "string", "build_variant_name", "flavor3" } flavor4 { resValue "string", "build_variant_name", "flavor4" } flavor5 { resValue "string", "build_variant_name", "flavor5" } } } //...other configs 

La clave aquí es la línea new File('app/build_variants.txt').eachLine { "$it" { resValue "string", "build_variant_name", "$it" } } . Lee el archivo 'app / build_variants.txt' y, para cada línea, genera un sabor de producto con el nombre en la línea que se lee. el $it es la línea en la que pasa. Simplemente la sintaxis de cierre groovy. Si quieres una comprensión más profunda. Recomiendo encarecidamente ver el video de @Daniel Lew sobre groovy y gradle. ¡Es impresionante!.

  • Gradle Android Build Project Error: No se pudo encontrar el recurso de metadatos
  • Utilice el paquete de un sabor en el manifiesto
  • Problema de actualización en la versión de herramientas de compilación de gradle de 1.2.3 a 1.3.1
  • Travis ci build failing - causa: PermGen espacio
  • ¿Por qué no degradar las clases Java en diferentes sabores de Android?
  • Depurar pruebas de unidad basadas en gradle con IntelliJ / AndroidStudio
  • Cómo crear un archivo de expansión de Android con Android Studio?
  • SignedConfigs me da un error de Lint en build.gradle después de actualizar a v22
  • ¿Qué hacer con los archivos .rawproto en el directorio de compilación de Android Studio?
  • Gradle: Plugin con id 'android-library' no encontrado
  • Utilizar Gradle para dividir bibliotecas externas en archivos separados dex para resolver el límite de métodos de Android Dalvik 64k
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.