¿Por qué Gradle?

Gradle es un avanzado toolkit de compilado que maneja dependencias y permite definir nuestra propia lógica de build.wrap

Pero, si ya existían Ant y Maven ¿por qué Gradle ahora?

  • Ant: Fue el primer build tools moderno, y se convirtió en el más popular para proyectos Java. Tiene una curva de aprendizaje muy pequeña. Configurado por XML, lo que lo lleva a ser poco manejable en cuanto crece un poco. Además se basa en una idea de programación por procedural, que no pega muy bien con la naturaleza jerárquica como XML. Utiliza Apache Ivy para gestionar las dependencias online.
  • Maven: Surgió más tarde para mejorar los problemas que había con Ant. Aunque utiliza también XML simplifica la creación de tareas en comparación con Ant. Permitió la descarga de dependencias online antes de que Ant incorporarse Ivy. Está más pensado para la gestión de dependencias, el personalizar los script es más complejo que en Ant. Igualmente, su formato XML lo dificulta para personalización.

 

Gradle combina lo mejor de cada uno, tiene la potencia y flexibilidad de Ant con la facilidad de uso de Maven…¡¡ pero sin XML!! Tiene un lenguaje específico de dominio (DSL) basado en Groovy (un lenguaje soportado por la máquina virtual de Java JVM), los scripts son mucho más cortos y claros, menos boilerplate. Soporta la automatización de descargas y configuración de dependencias de proyectos/librerías (soporta repositorios Maven e Ivy).  Es muy flexible, permite usar buenas prácticas pero no obliga a la forma en que se hacen las cosas. Los plugins pueden exponer su propio DSL y API para ser reutilizado.

 

Android Studio adoptó Gradle en 2014 como herramienta para construir los proyectos y añade algunas características extra para Android. Utiliza un wrapper para integrar el plugin y correrlo independientemente (se puede compilar las apps desde el Android Studio como desde la línea de comandos).

Actualmente la versión de Gradle va por la v4.2, los diferentes plugin de Android permiten seleccionar una versión diferente:

 

Android Plugin Version de Gradle
1.0.0 – 1.1.3 2.2.1 – 2.3
1.2.0 – 1.3.1 2.2.1 – 2.9
1.5.0 2.2.1 – 2.13
2.0.0 – 2.1.2 2.10 – 2.13
 2.1.3 – 2.2.3 2.14.1 +
2.3.0 + 3.3 +

 

Algunos conceptos básicos de Gradle

 

Build types

Permite la configuración de cómo se va a empaquetar la aplicación para debugging o release (local, debug, staging, quality, release, …). Se controlan campos como el debug flag, minify con proguard, signing config, suffix …

 

Product flavors

Define una versión personalizada de la aplicación. Un mismo proyecto puede tener diferentes flavor (free, premium, Google store, Amazon store, …)

Cuando un proyecto declara diferentes flavors, estos extienden de la configuración principal pudiendo tener su propio código y recursos.

A pesar de que diferentes flavors pueden ser diferentes aplicaciones, usar librerías de proyectos puede ser mejor opción. Los flavors están diseñados para ayudar cuando las diferencias son muy pero que muy pequeñas.

 

Variants

con flavor → variant = build type + product flavor

sin flavor → variant = build type

 

free premium
local freeLocal  premiumLocal
quality freeQuality premiumQuality
staging freeStaging premiumStaging
release freeRelease premiumRelease

 

 

BuildConfig

Se pueden crear valores dinámicos en función del variant, así podemos configurar la aplicación para diferentes entornos. En tiempo de compilación se genera la clase BuildConfig.java que contiene constantes usadas para un determinado variant, esta clase es accesible en la app para arrancar nuestra base de datos, acceso a red, etc con esa configuración.

 

 

 

Dependencias

A veces tenemos dependencias en los paquetes que provocan conflictos en sus dependencias transitivas. Una solución es excluir las dependencias específicas de un módulo:

o si tenemos múltiples dependencias y queremos excluir una lib en todas ellas:

Es posible forzar Gradle para que use una versión específica siempre que encuentre un conflicto.

 

API version

En la configuración del API en Gradle es muy importante las versiones que se indican para compilar, target, las librerías de dependencias, etc.:

  • minSdkVersion: la mínima versión de Android en el que la app puede funcionar.
  • compileSdkVersion: versión del API sobre el que se compila el apk. El major del API de las librerías de dependencias debe ser igual al del compileSdkVersion.
  • buildToolsVersion: versión de los compiladores (aapt, dx, renderscript compiler, etc…) que se van a usar. Para cada nivel API (comenzando en el 18) hay versiones “.0.0” que se pueden incrementar para utilizar las mejoras sin cambiar el API sobre el que se va a construir. El major del buildToolsVersion debe ser mayor o igual al del compileSdkVersion.
  • targetSdkVersion: versión a la que se dirige la app por temas de rendimiento, optimización, etc.  Suele ser igual al compileSdkVersion,  pero no debe ser mayor.

 

Android Model

Desde Android Studio 1.5 hay un nuevo componente de integración con Gradle que muestra toda la configuración de BuildTypes, ProductFlavors, Variants, BuildConfig, ResValues, etc.

 

En el Android Studio podemos seleccionar el Android Model, en Variants → [ProductFlavor] → Artifacts → _main tenemos toda la configuración generada al compilar el gradle:

  • BuildConfigFields: todas las constantes de la clase generada BuildConfig.java

Android - Gigigo

  • Outputs: manifest, APK generados
  • ResValues: resvalues generados

Android Model - Gigigo

  • Sources: estructura de todas las carpetas de la app (manifest, java, jni, res, assets, …)

 

 

Wrapper

Hay dos maneras de ejecutar Gradle en el equipo: instalado localmente en el equipo (nunca lo utilizaremos) o por medio del wrapper de cada proyecto. Podemos cambiar esto en Preferences → Build Tools → Gradle. Siempre usaremos el wrapper del proyecto para el build del sistema, así evitamos problemas entre diferentes equipos de desarrollo.

Se puede especificar al wrapper de Gradle que utilice una versión diferente. Para poder actualizar esta versión hay que irse al archivo gradle/wrapper/gradle-wrapper.properties y modificar la propiedad:

o por medio de Project Structure → Project modificando el Gradle version.

 

Offline

Siempre que sincronicemos el Gradle del proyecto, se descargará las librerías de la web. Si no queremos que realice esta descarga siempre, o si estamos sin conexión a internet en el equipo podemos indicarle en Preferences → Build Tools → Gradle → Offline work que trabaje en offline y guarde las dependencias.

 

Conclusión

La automatización de ciertas tareas es algo muy importante. El cambiar de entornos para probar la app contra el servidor de staging, quality o las subidas a producción. Las url de back para diferentes endpoint, los id de Facebook o para las analíticas. Todo esto nos puede quitar tiempo de desarrollo y es muy propenso a fallos como muchos, antes comentábamos/descomentamos líneas, o usábamos diferentes .java en cada flavor para cambiar la configuración de entorno, o introducíamos valores String para el BuildConfig pero escapando las comillas, etc.

Para evitar esto, hace tiempo modificamos el procedimiento de construcción de los proyectos para automatizarlo con Gradle. Ahora el cambio de entorno, la configuración para test, o la integración en Jenkins para CI/CD es mucho más rápida y sencilla.

 

Aunque continuamente lo vamos mejorando, se puede ver una base aquí

Senior Developer & Android Team Leader en Gigigo. Tri-Fada & Babies Developer 👦👧👧