Crear una biblioteca de Android

Una biblioteca de Android es estructuralmente igual a un módulo de app de Android. Puede incluir todo lo que se necesita para compilar una app, como el código fuente, archivos de recursos y un manifiesto de Android. Sin embargo, en lugar de compilarse en un APK que se ejecute en un dispositivo, una biblioteca de Android se compila en un archivo Android Archive (AAR) que puedes usar como dependencia para un módulo de app de Android. A diferencia de los archivos JAR, los archivos AAR contienen recursos de Android y un archivo de manifiesto, que te permite contener recursos compartidos como diseños y elementos de diseño además de las clases y los métodos Java.

Un módulo de biblioteca es útil en las siguientes situaciones:

  • Cuando compilas varias apps que comparten algunos componentes, esas actividades, servicios o diseños de IU.
  • Cuando compilas una app que existe en diferentes variaciones de APK, como una versión gratuita o paga, y necesitas los principales componentes en ambas.

En cualquier caso, simplemente mueve los archivos que desees volver a usar a un módulo de biblioteca y luego agrégala como una dependencia para cada módulo de app. En esta página, aprenderás los dos procedimientos.

Crear un módulo de biblioteca

Para crear un módulo de biblioteca en tu proyecto, procede de la siguiente manera:

  1. Haz clic en File > New > New Module.
  2. En la ventana Create New Module que aparece, haz clic en Android Library y luego en Next.

    También existe la opción de crear una biblioteca Java que compile un archivo JAR tradicional. Aunque un archivo JAR es útil para muchos proyectos, en especial cuando deseas compartir el código con otras plataformas, no te permite incluir recursos de Android ni archivos de manifiesto, lo cual es muy útil para reutilizar el código en proyectos de Android. Por ello, esta guía se centra en bibliotecas de Android.

  3. Otorga un nombre a tu biblioteca y selecciona una versión de SDK mínima para el código en la biblioteca. Luego haz clic en Finish.

Una vez que se complete la sincronización del proyecto de Gradle, el módulo de la biblioteca aparecerá en el panel Project, a la izquierda. Si no ves la carpeta del módulo nueva, asegúrate de que se muestre la vista de Android.

Convertir un módulo de app en un módulo de biblioteca

Si tienes un módulo de app existente con todos los códigos que desees reutilizar, puedes convertirlo en un módulo de biblioteca de la siguiente manera:

  1. Abre el archivo build.gradle del módulo de app existente. En la parte superior, verás lo siguiente:
    apply plugin: 'com.android.application'
    
  2. Cambia la asignación del complemento como se muestra aquí:

    apply plugin: 'com.android.library'
    
  3. Haz clic en Sync Project with Gradle Files.

Eso es todo. Toda la estructura del módulo seguirá siendo igual, aunque ahora funcionará como una biblioteca de Android y la compilación creará un archivo AAR en lugar de un APK.

Agregar tu biblioteca como dependencia

Para usar el código de tu biblioteca de Android en otro módulo de app, procede de la siguiente manera:

  1. Agrega la biblioteca a tu proyecto de dos maneras (si creaste el módulo de biblioteca dentro del mismo proyecto, ya estará allí y podrás omitir este paso):
    • Agrega el archivo AAR compilado (o JAR):
      1. Haz clic en File > New Module.
      2. Haz clic en Import .JAR/.AAR Package y luego en Next.
      3. Ingresa la ubicación del archivo AAR o JAR y luego haz clic en Finish
    • Importa el módulo de biblioteca a tu proyecto:
      1. Haz clic en File > New > Import Module.
      2. Ingresa la ubicación del directorio del módulo de biblioteca y luego haz clic en Finish.

      El módulo de biblioteca se copia a tu proyecto, para que realmente puedas editar el código de biblioteca. Si deseas mantener una única versión del código de biblioteca, probablemente esto no sea lo que buscas y, como alternativa, debes importar el archivo AAR compilado como se describe anteriormente.

  2. Asegúrate de que la biblioteca se ubique en la parte superior de tu archivo settings.gradle, como se muestra aquí para una biblioteca llamada “my-library-module”:
    include ':app', ':my-library-module'
    
  3. Abre el archivo build.gradle del módulo de la app y agrega una línea nueva al bloque de dependencies como se muestra en el siguiente fragmento:
    dependencies {
        compile project(":my-library-module")
    }
    
  4. Haz clic en Sync Project with Gradle Files.

En el ejemplo anterior, el módulo de la biblioteca de Android llamada my-library- module se convierte en una dependencia de compilación para el módulo en el cual reside el archivo build.gradle.

Cualquier código o recurso de la biblioteca de Android ahora se encontrará disponible para tu módulo de app y el archivo AAR de la biblioteca se integrará a tu APK en el momento de la compilación.

Sin embargo, si deseas compartir tu archivo AAR por separado, puedes encontrarlo en project-name/module-name/build/outputs/aar/ y regenerarlo haciendo clic en Build > Make Project.

Seleccionar recursos para la publicación

El valor predeterminado de todos los recursos de una biblioteca es “public”. Para hacer que todos los recursos sean implícitamente privados, debes definir al menos un atributo específico como público. Los recursos incluyen todos los archivos en el directorio de tu proyecto res/, como las imágenes. Para evitar que los usuarios de tu biblioteca accedan a recursos previstos únicamente para uso interno, debes usar este mecanismo de designación privado automático declarando uno o más recursos.

Para declarar un recurso público, agrega una declaración al archivo de tu biblioteca public.xml. Si no has agregado recursos públicos anteriormente, debes crear el archivo public.xml en el directorio res/values/ de tu biblioteca.

El siguiente ejemplo de código crea dos recursos públicos de string con los nombres mylib_app_name y mylib_public_string:

<resources>
    <public name="mylib_app_name" type="string"/>
    <public name="mylib_public_string" type="string"/>
</resources>

Debes hacer público cualquier recurso que desees mantener visible para los desarrolladores usando tu biblioteca. Por ejemplo, aunque la mayoría de los recursos de la biblioteca appcompat v7 son privados, los atributos que controlan el widget de la barra de herramientas son públicos para admitir material design.

Hacer los atributos privados de modo implícito no solo evita que los usuarios de tu biblioteca reciban sugerencias de compleción de código a través de recursos internos de biblioteca, sino también te permite volver a nombrar o eliminar recursos privados sin afectar a los clientes de tu biblioteca. Los recursos privados se eliminan mediante filtrado del código completo, y el editor de tema y Lint te advierten cuando intentas hacer referencia a un recurso privado.

Consideraciones para el desarrollo

Cuando desarrolles tus módulos de biblioteca y las apps dependientes, ten en cuenta los comportamientos y las limitaciones siguientes.

Una vez que agregues referencias a módulos de biblioteca a tu módulo de app de Android, puedes establecer su prioridad relativa. En el momento de la compilación, las bibliotecas se combinan con la app de a una, de menor a mayor prioridad.

  • Conflictos de combinación de recursos

    Las herramientas de compilación combinan los recursos de un módulo de biblioteca con los de un módulo de app dependiente. Si un ID del recurso dado se define en ambos módulos, se usa el recurso de la app.

    Si ocurren conflictos entre varias bibliotecas AAR, se usa el recurso de la biblioteca que se ubica primero en la lista de dependencias (en la parte superior del bloque de dependencies).

    Para evitar conflictos de recursos para los ID de recursos más comunes, considera usar un prefijo u otro esquema de nombramiento uniforme que sea exclusivo del módulo (o en todos los módulos del proyecto).

  • Un módulo de biblioteca puede incluir una biblioteca JAR

    Puedes desarrollar un módulo de biblioteca que incluya una biblioteca JAR; sin embargo, debes editar manualmente la ruta de acceso de compilación de los módulos de app dependientes y agregar una ruta de acceso al archivo JAR.

  • Un módulo de biblioteca puede depender de una biblioteca JAR externa

    Puedes desarrollar un módulo de biblioteca que dependa de una biblioteca externa (por ejemplo, la biblioteca externa de mapas). En este caso, la app dependiente debe realizar compilaciones en un objetivo que incluya la biblioteca externa (por ejemplo, los complementos de Google API). Ten en cuenta que el módulo de biblioteca y la app dependiente deben declarar la biblioteca externa en sus archivos de manifiesto, en un elemento <uses- library>.

  • Los módulos de biblioteca no pueden incluir recursos sin procesar

    Las herramientas no admiten el uso de archivos con activos sin procesar (guardados en el directorio assets/) en un módulo de biblioteca. Cualquier recurso de activos usado por una app se debe almacenar en el directorio assets/ del módulo de la app.

  • El valor minSdkVersion del módulo de la app debe ser igual o superior a la versión definida por la biblioteca

    Una biblioteca se compila como parte del módulo de app dependiente; por ello, las API que se usan en el módulo de biblioteca deben ser compatibles con la versión de plataforma que el módulo de app admita.

  • Cada módulo de biblioteca crea su propia clase R

    Cuando compilas los módulos de app dependientes, los módulos de biblioteca se compilan en un archivo AAR y luego se agregan al módulo de app. Por lo tanto, cada biblioteca tiene su propia clase R cuyo nombre responde al nombre del paquete de la biblioteca. La clase R se genera desde el módulo principal y el módulo de biblioteca se crea en todos los paquetes necesarios, incluidos el paquete principal del módulo y los paquetes de las bibliotecas.

  • Los módulos de biblioteca pueden incluir su propio archivo de configuración ProGuard

    Puedes habilitar la reducción de código en tu biblioteca agregando un archivo de configuración ProGuard a tu biblioteca que incluya sus directivas de ProGuard. Las herramientas de compilación incorporan este archivo dentro del archivo AAR generado para el módulo de biblioteca. Cuando agregas la biblioteca a un módulo de app, el archivo ProGuard de la biblioteca se anexa al archivo de configuración de ProGuard (proguard.txt) del módulo de app.

    Al incorporar un archivo ProGuard en tu módulo de biblioteca, garantizas que los módulos de app que dependen de tu biblioteca no deban actualizar manualmente sus archivos ProGuard para usar tu biblioteca. Cuando se ejecuta en el módulo de la app de Android, ProGuard usa las directivas del módulo de app y de la biblioteca. Por ello, no debes ejecutarlo solo en la biblioteca.

    Para especificar el nombre del archivo de configuración de tu biblioteca, agrégalo al método consumerProguardFiles, dentro del bloque defaultConfig del archivo de tu biblioteca build.gradle. Por ejemplo, en el siguiente fragmento se establece lib-proguard-rules.txt como archivo de configuración ProGuard de la biblioteca:

    android {
        defaultConfig {
            consumerProguardFiles 'lib-proguard-rules.txt'
        }
        ...
    }
    

    De forma predeterminada, el módulo de la app usa la compilación de lanzamiento de la biblioteca, incluso cuando se usa el tipo de compilación de depuración del módulo de la app. Para usar un tipo de compilación diferente de la biblioteca, debes agregar dependencias al bloque de dependencies del archivo build.gradle de la app y fijar publishNonDefault en true en el archivo build.gradle de la biblioteca. Por ejemplo, el siguiente fragmento de código del archivo build.gradle de tu app hace que esta use el tipo de compilación de depuración de la biblioteca cuando el módulo de app se compila en el modo de depuración, y también que use el tipo de compilación de lanzamiento de la biblioteca cuando el módulo de app se compila en el modo de lanzamiento:

    dependencies {
        debugCompile project(path: ':library', configuration: 'debug')
        releaseCompile project(path: ':library', configuration: 'release')
    }
    

    También debes agregar la siguiente línea dentro del bloque android del archivo build.gradle de tu biblioteca para dejar expuestas las configuraciones sin lanzamiento de tu biblioteca a proyectos que la usen:

    android {
        ...
        publishNonDefault true
    }
    

    Sin embargo, ten en cuenta que la configuración de publishNonDefault puede aumentar los tiempos de compilación.

    Para asegurarte de que las reglas de ProGuard de la biblioteca no apliquen efectos secundarios de reducción no deseados en los módulos de app, solo incluye reglas que inhabiliten las características ProGuard que no funcionen con tu biblioteca. Las reglas pensadas para intentar ayudar a desarrolladores pueden entrar en conflicto con el código existente en un módulo de app o en sus otras bibliotecas y, por lo tanto, no deberán incluirse. Por ejemplo, en el archivo ProGuard de tu biblioteca se puede especificar el código que debe conservarse durante la minificación de un módulo de app.

    Nota: El nuevo conjunto de herramientas Jack proporciona compatibilidad con solo algunas opciones de reducción y ocultamiento de ProGuard.

Anatomía de un archivo AAR

La extensión de archivo para un archivo AAR es .aar y el tipo de artefacto de Maven también debe ser aar. El archivo es de tipo zip y contiene las siguientes entradas obligatorias:

  • /AndroidManifest.xml
  • /classes.jar
  • /res/
  • /R.txt

Además, un archivo AAR puede incluir una o más de las siguientes entradas opcionales:

  • /assets/
  • /libs/name.jar
  • /jni/abi_name/name.so (donde abi_name es una de las ABI admitidas de Android)
  • /proguard.txt
  • /lint.jar