tools studio para now must flavors flavor descargar configurar belong all android android-gradle android-build android-productflavors android-sourcesets

para - configurar gradle android studio



Generación dinámica de productFlavors y sourceSets utilizando una lista de nombres(con propiedades) en un archivo CSV/TXT (2)

Esta pregunta en la continuación de mi otra pregunta , que quiero mejorar aún más.

Puedo agrupar sabores (que tienen una configuración común) en sourceSets con el siguiente código:

(Lo obtuve de un genio en la pregunta vinculada más arriba)

import com.android.build.gradle.api.AndroidSourceSet android { sourceSets { [flavor2, flavor4].each { AndroidSourceSet ss -> ss.assets.srcDirs = [''repo-assets/flavor2''] ss.res.srcDirs = [''repo-res/flavor2''] } } }

Ahora, me preguntaba si la lista [flavor2, flavor4] podría extraerse de cualquiera de los siguientes:

  • Un archivo XML sobre el cual puedo iterar para obtener todos los sabores (que pondré allí)
  • Un archivo CSV sobre el cual puedo iterar y obtener valores.
  • Una clase personalizada que puedo escribir en un archivo separado y obtener datos de miembros estáticos en la clase.

Además del nombre del sabor, tengo la intención de almacenar lo siguiente en la fuente externa (una de las anteriores):

  • ID de la aplicación (que voy a productFlavors para productFlavors )
  • Id. del bloque de anuncios (dos por sabor)
  • algunos otros valores personalizados como categoría, etc.

PORPOSE: Quiero escribir una pieza genérica de código para iterar y crear dinámicamente los sourceSets y los sourceSets . He generalizado sourceSets a casi 90% y un bloque ahora es suficiente para todos los sabores.

Se ve algo como esto ahora:

sourceSets { [flavor1, flavor2, flavor3 ...].each { AndroidSourceSet ss -> ss.assets.srcDirs = [''repo-assets/'' + ss.name.split(''_'')[0]] ss.res.srcDirs = [''repo-mipmap/'' + ss.name.split(''_'')[0] , ''repo-strings/'' + ss.name] } }

También quiero hacer lo mismo con productFlavors como se indicó anteriormente.

STUCK AT: obteniendo la lista [flavor2, flavor4] en el código anterior de una fuente externa (junto con algunos campos adicionales por sabor, como se indica más arriba).

Veo métodos como

productFlavors.add() productFlavors.addAll()

pero no estoy muy seguro de cómo usar estos. Como los métodos están disponibles, estoy seguro de que es posible hacer lo que intento.

¿Alguien ha hecho esto y tiene algunos consejos?


Finalmente lo hice funcionar de esta manera:

Creé una clase personalizada MyFlavor dentro de build.gradle y agregué cada sabor del archivo csv a una ArrayList de MyFlavor

class MyFlavor { public String flavorname; public String basename; public String appid; public String bannerid; public String interstitialid; public String category; } def ArrayList<MyFlavor> myFlavors = new ArrayList<>(); new File(''app/flavors.csv'').eachLine { String[] values = "$it".split('',''); MyFlavor f = new MyFlavor(); f.flavorname = values[0]; f.basename = values[0].split(''_'')[0]; f.appid = values[1]; f.bannerid = values[2]; f.interstitialid = values[3]; if(values[0].contains(''_'')) f.category= "state" else f.category = "country"; myFlavors.add(f); }

A continuación, se repitió sobre ArrayList para crear dinámicamente los sourceSets y los sourceSets siguiente manera:

productFlavors { myFlavors.each { MyFlavor f -> "$f.flavorname" { applicationId = "$f.appid" buildConfigField ''String'', ''BANNER_ID'', "/"" + "$f.bannerid" + "/"" buildConfigField ''String'', ''INTERSTITIAL_ID'', "/"" + "$f.interstitialid" + "/"" buildConfigField ''String'', ''CATEGORY'', "/"" + "$f.category" + "/"" } } } sourceSets { myFlavors.each { MyFlavor f -> "$f.flavorname" { assets.srcDirs = [''repo-assets/'' + "$f.basename"] res.srcDirs = [''repo-mipmap/'' + "$f.basename" , ''repo-strings/'' + "$f.flavorname"] } } }

Espero que esto ayude a alguien. Tuve éxito en deshacerme de miles de líneas de código (porque tengo muchos sabores) y reducirlo a estas 10 líneas que ves aquí.


Para leer archivos XML y CSV, tiene todo el poder de Groovy en sus manos. Todos los scripts Gradle están escritos en Groovy. .each { Type var -> es parte de eso también. Primer resultado: https://.com/a/2622965/253468 :

Dado un archivo CSV como este:

#name,appId,ad1,ad2,category flavor1,app.id.flavor1,adunit1324523,adunit2234234,messenger flavor2,app.id.flavor2,adunit42346451,adunit4562,editor flavor3,app.id.flavor2.gpe,adunit345351,adunit3545342,messenger

Groovy puede cargarlo así:

import com.android.build.gradle.BaseExtension import com.android.build.gradle.api.AndroidSourceSet import com.android.build.gradle.internal.dsl.ProductFlavor // TODO get a real CSV parser, this is hacky new File("flavors.csv").splitEachLine(",") { fields -> if (fields[0].charAt(0) == ''#'' as char) return; // skip comments def flavorName = fields[0]; def baseName = flavorName.split(''_'')[0]; def appId = fields[1]; BaseExtension android = project.android // project.getExtensions().getByName(''android''); // productFlavors is declared as Collection, but it is a NamedDomainObjectContainer // if [flavorName] doesn''t work, try .maybeCreate(flavorName) or .create(flavorName) ProductFlavor flavor = android.productFlavors[flavorName]; AndroidSourceSet sourceSet = android.sourceSets[flavorName]; flavor.applicationId = appId; sourceSet.res.srcDirs = [] // clear sourceSet.res.srcDir ''repo-mipmap/'' + baseName sourceSet.res.srcDir ''repo-strings/'' + flavorName }

Los tipos se importan para la legibilidad y la finalización del código, puede reemplazar cualquier tipo de variable con def y aún así funcionará. Estos tipos son solo lo que se usa cuando estás haciendo la configuración regular de android { ... } . Los tipos internos pueden cambiar en cualquier momento, de hecho, estoy trabajando con 1.5; es posible que ya hayan cambiado en 2.0.