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!.

  • Creando un archivo apk de depuración usando gradle en error de servidor sin cabeza
  • ¿Por qué no puede androide gradle encontrar junit? ¿Por qué no lo está buscando en repositorios remotos?
  • ¿Cómo configuro la versión Gradle en Android Studio 1.3?
  • ¿Es posible integrar Dagger y AspectJ en un proyecto de Android Studio?
  • ¿Cómo configurar el módulo de la Biblioteca de Android y ser referenciado por varios proyectos en Android Studio?
  • Gradle no funciona: Error de ejecución para la tarea ': MyApp: compileDebug'
  • Gradle: Cómo excluir javax.realtime paquete de JScience jar dependencia (Multiple dex define)
  • Minify la aplicación para Android, pero no la ofusque
  • Firmar APK sin poner información de almacén de claves en build.gradle
  • Construir apk con error gradle
  • Cómo quitar comentarios en archivos XML sin procesar con Gradle cuando el archivo se empaqueta
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.