Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


¿Cómo tener dos sabores de construcción heredar de un sabor de raíz en Android Studio?

Solía ​​tener los siguientes sabores del proyecto:

  1. manzana
  2. naranja

Originalmente, la única diferencia era el applicationId/packageName . Ahora hay un único archivo java que es diferente. Un ArrayAdapter personalizado para ser exactos. La solución fue crear src/Apple y src/Orange y ambos heredar de src/main . Quité el archivo de java de src/main y puse una copia en src/Apple y src/Orange y lo modifiqué apropiadamente. Todo era bueno en el mundo.

Avance rápido de unas pocas semanas, ahora hay unos 10 archivos java que difieren entre Apple y Orange. De nuevo … no es gran cosa. Facil de manejar. Separa archivos java en src/Apple y src/Orange .

Avance rápido a hoy. Necesito modificar un poco las cosas, porque quiero tener una versión gratuita y premium de cada una. Las versiones gratuitas y premium solo difieren según una URL. Iba a simplemente crear los nuevos tipos llamados:

  1. AppleFree
  2. ApplePremium
  3. Naranja
  4. OrangePremium

Tengo un dilema sin embargo. Desde ahora src/Apple y src/Orange tienen 10 archivos diferentes que se han cambiado … si cambio cualquier archivo java en AppleFree tengo que asegurarme de hacer lo mismo en ApplePremium . Estoy un poco en una encrucijada y espero que mi pregunta tenga sentido en este momento. He llegado con tres posibles soluciones, pero no estoy seguro de cómo lo implementaría / cuál sería el enfoque correcto / la solución no es lo que quiero.

Solución 1:

Utilice una instrucción if (BuildConfig.FLAVOR==appleFree) {//use free Url} else {// use premium url}

Problema: Ambos URL están técnicamente compilados en el apk. No quiero esto.

Solución 2:

Han src / AppleFree y src / ApplePremium heredan de algún directorio padre src / Apple de alguna manera.

Problema: No estoy seguro de cómo haría esto.

Solución 3:

Añadir el derecho de url libre y premium en build.gradle así?

  productFlavors { appleFree { applicationId "com.example.apple.free" versionName "1.0" url "http://freeurl.com" versionCode 1 } applePremium { applicationId "com.example.apple.premium" versionName "1.0" url "http://premiumurl.com" versionCode 1 } orangeFree { applicationId "com.example.orange.free" versionName "1.0" versionCode 1 url "http://freeurl.com" } orangePremium { applicationId "com.example.orange.premium" url "http://premiumurl.com" versionName "1.0" versionCode 1 } } 

Problema: No estoy seguro de cómo hacer que funcione.

Cualquier sugerencia es útil.

EDITAR:

¿Solución final?

 flavorGroups 'fruit', 'paid' productFlavors { apple { flavorGroup 'fruit' } orange { flavorGroup 'fruit' } free { flavorGroup 'paid' } premium { flavorGroup 'paid' } appleFree { applicationId "com.example.apple.free" versionName "1.0" buildConfigField 'String', 'BASE_URL', 'http://freeurl.com' versionCode 1 } applePremium { applicationId "com.example.apple.premium" versionName "1.0" buildConfigField 'String', 'BASE_URL', 'http://premiumurl.com' versionCode 1 } orangeFree { applicationId "com.example.orange.free" versionName "1.0" versionCode 1 buildConfigField 'String', 'BASE_URL', 'http://freeurl.com' } orangePremium { applicationId "com.example.orange.premium" buildConfigField 'String', 'BASE_URL', 'http://premiumurl.com' versionName "1.0" versionCode 1 } } 

  • No se pudo actualizar el proyecto Gradle
  • Cómo configurar gradle-2.2.1-all.zip manualmente
  • El primer lanzamiento tarda mucho tiempo (ClassLoader hace referencia al camino desconocido)
  • ¿Cómo especificar la versión de JDK en android studio?
  • ¿Por qué Android Studio no encuentra mis recursos?
  • Error de ejecución de Gradle en Android Studio (Ubuntu)
  • Definir buildConfigField para androidTest
  • DEX falla al analizar un frasco incluyendo BuildConfig y R usando Gradle, pero trabajó con Ant
  • One Solution collect form web for “¿Cómo tener dos sabores de construcción heredar de un sabor de raíz en Android Studio?”

    Hay muchas soluciones posibles a su problema. La solución más nativa de Gradle sería utilizar las Dimensiones de Sabor, como se documenta en http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Multi-flavor-variants

    Esto también es similar a lo que estaba pensando en la solución 2.

    Funcionaría algo como esto:

     flavorDimensions 'fruit', 'paid' productFlavors { apple { dimension 'fruit' } orange { dimension 'fruit' } free { dimension 'paid' } premium { dimension 'paid' } } 

    Esto le dará las variantes de construcción (y las carpetas de origen) donde hace la combinación de todas las posibilidades de cada dimensión de sabor, manteniendo el mismo orden de cómo se especifican los grupos en la instrucción flavorDimensions (es decir, appleFree , no freeApple )

     * appleFree * applePremium * orangeFree * orangePremium 

    En su carpeta src / , puede tener estas posibilidades:

     * src/main * src/apple * src/orange * src/free * src/premium * src/appleFree * src/applePremium * src/orangeFree * src/orangePremium 

    Solución 3

    Puede utilizar el buildConfigField para especificar las constantes que van en la clase BuildConfig en función del sabor por el sabor:

     productFlavors { appleFree { buildConfigField 'String', 'MY_URL', 'value1' } applePremium { buildConfigField 'String', 'MY_URL', 'value2' } orangeFree { buildConfigField 'String', 'MY_URL', 'value3' } orangePremium { buildConfigField 'String', 'MY_URL', 'value4' } 

    Solución 1

    Yo estaba tratando de trabajar en algo a lo largo de las líneas de la Solución 1, pero no funcionará bien para su caso de uso exacto. Si tiene una condición if en Java que prueba contra un booleano declarado static final entonces el compilador puede determinar de forma estática si el código es accesible o no, y lo quitará si no lo es. Así:

     static final boolean DEBUG = false; ... if (DEBUG) { // do something } 

    El código en // do something no se compilará en absoluto. Este es un comportamiento intencional y documentado por parte del compilador de Java, y le permite escribir costoso código de depuración que no se compilará en su binario de versión. BuildConfig.DEBUG se declara como static final por este motivo exacto.

    Hay un BuildConfig.FLAVOR , pero se define como String y no obtiene el mismo beneficio:

     static final String FLAVOR = "orange"; ... if (FLAVOR.equals("apple")) { // do something } 

    El compilador no es lo suficientemente inteligente como para hacer el análisis estático, vea que // do something inalcanzable y no lo compila. Tenga en cuenta que funcionará bien en tiempo de ejecución , pero ese código muerto se incluirá en su binario.

    Si te conviene, puedes robar el método buildConfigField desde arriba y definir una variable booleana extra en algunas variantes que podrían permitir que el código se compile condicionalmente. Esto es más complejo que definir la cadena directamente como en la Solución 3 , pero si Te encuentras deseando diferenciar el comportamiento sin pasar por el problema de hacer subclases específicas del sabor, puedes ir por esta ruta.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.