Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Cómo crear una biblioteca de Android

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

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

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

En cualquier caso, mueve los archivos que desees volver a usar a un módulo de biblioteca y, luego, agrega la biblioteca como una dependencia para cada módulo de app. En esta página, se muestran los dos procedimientos.

Cómo crear un módulo de biblioteca

Para crear un módulo de biblioteca en tu proyecto, haz lo siguiente:

  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 se puede crear una biblioteca Java, que compila un archivo JAR tradicional. Si bien un archivo JAR es útil para muchos proyectos, en especial cuando deseas compartir el código con otras plataformas, no te permite incluir archivos de manifiesto ni recursos de Android, y esto es muy útil para reutilizar el código en proyectos de Android. Por ello, esta guía se enfoca en la creación de bibliotecas de Android.

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

Una vez que se haya completado la sincronización del proyecto de Gradle, se mostrará el módulo de la biblioteca en el panel Project de la izquierda. Si no se muestra la carpeta del módulo nuevo, asegúrate de que se muestre en la vista Android.

Cómo 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 deseas reutilizar, puedes convertirlo en un módulo de biblioteca de la siguiente manera:

  1. Abre el archivo build.gradle de nivel de módulo.
  2. Borra la línea de applicationId. Solo un módulo de aplicación de Android puede definir esto.
  3. En la parte superior del archivo, se mostrará lo siguiente:
        apply plugin: 'com.android.application'
        

    Cámbialo por lo siguiente:

        apply plugin: 'com.android.library'
        
  4. Guarda el archivo y haz clic en File > Sync Project with Gradle Files.

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

Cuando desees compilar el archivo AAR, selecciona el módulo de biblioteca en la ventana Project y, luego, haz clic en Build > Build APK.

Cómo agregar la biblioteca como dependencia

Para usar el código de la biblioteca de Android en otro módulo de app, haz lo siguiente:

  1. Agrega la biblioteca al proyecto de cualquiera de las siguientes maneras (si creaste el módulo de biblioteca dentro del mismo proyecto, ya estará allí y puedes omitir este paso):
    • Agrega el archivo AAR compilado (o JAR) (la biblioteca ya debe estar compilada):
      1. Haz clic en File > New > New Module.
      2. Haz clic en Import.JAR/.AAR Package y, luego, en Next.
      3. Ingresa la ubicación del archivo AAR o JAR. Luego, haz clic en Finish.
    • Importa el módulo de biblioteca al proyecto (la fuente de la biblioteca se convierte en parte del 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 en tu proyecto para que puedas editar el código de biblioteca. Si deseas mantener una única versión del código de biblioteca, entonces esto no sea lo que deberías hacer. En su lugar, debes agregar el archivo AAR compilado como se describió anteriormente.

  2. Asegúrate de que se muestre la biblioteca en la parte superior del archivo settings.gradle, como se muestra aquí para una biblioteca denominada "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 dependencies, como se muestra en el siguiente fragmento:
        dependencies {
            implementation project(":my-library-module")
        }
        
  4. Haz clic en Sync Project with Gradle Files.

En este ejemplo anterior, la configuración de implementation agrega la biblioteca denominada my-library-module como dependencia de compilación para todo el módulo de la app. Si, en cambio, solo quieres usar la biblioteca para una variante de compilación específica, en lugar de implementation, utiliza buildVariantNameImplementation. Por ejemplo, si deseas incluir la biblioteca solo en el tipo de producto "pro", se mostrará lo siguiente:

    productFlavors {
        pro { ... }
    }
    dependencies {
        proImplementation project(":my-library-module")
    }
    

Cualquier código o recurso de la biblioteca de Android ahora estará disponible para el módulo de tu app y, durante la compilación, se empaquetará el archivo AAR de la biblioteca en tu APK.

Sin embargo, si deseas compartir tu archivo AAR de forma separada, puedes encontrarlo en project-name/module-name/build/outputs/aar/ y volver a generarlo haciendo en Build > Make Project.

Nota: Para obtener más información sobre la administración de dependencias, consulta Cómo usar la administración de dependencias con detección de variantes.

Cómo seleccionar recursos para publicación

El valor predeterminado de todos los recursos de una biblioteca es "public". Para hacer que todos los recursos sean privados de forma implícita, debes definir al menos un atributo específico como "public". Los recursos incluyen todos los archivos ubicados en el directorio res/ del proyecto, como imágenes. Para evitar que los usuarios de la biblioteca accedan a recursos previstos únicamente para uso interno, debes utilizar este mecanismo de designación privado automático mediante la declaración de uno o más recursos públicos. De forma alternativa, puedes convertir todos los recursos en privados si agregas una etiqueta <public /> vacía, que no marca nada como público, sino todo como privado (todos los recursos).

Para declarar un recurso público, agrega una declaración <public> al archivo public.xml de la biblioteca. Si no agregaste recursos públicos antes, deberás crear el archivo public.xml en el directorio res/values/ de la biblioteca.

En el siguiente código de ejemplo, se crean dos recursos de string públicos 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 que usen tu biblioteca.

Hacer los atributos privados de modo implícito no solo evita que los usuarios de la biblioteca reciban sugerencias de finalización de código a través de recursos internos de biblioteca, sino que también permite renombrar o quitar recursos privados sin afectar a los clientes de la biblioteca. Los recursos privados se filtran al finalizar el código y Lint muestra una advertencia cuando intentas hacer referencia a un recurso privado.

Al compilar una biblioteca, el complemento de Gradle para Android obtiene las definiciones de recursos públicos y las extrae en el archivo public.txt, que luego se empaqueta dentro del archivo AAR.

Consideraciones de desarrollo para módulos de biblioteca

Cuando desarrolles los módulos de biblioteca y las apps dependientes, ten en cuenta los comportamientos y las limitaciones que se indican a continuación.

Una vez que hayas agregado referencias a módulos de biblioteca en el módulo de app de Android, podrás establecer su prioridad relativa. Durante la compilación, se combinarán las bibliotecas 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 se define un identificador de recurso específico en ambos módulos, se usará el recurso de la app.

    Si se generan conflictos entre varias bibliotecas de AAR, se usará el recurso que se ubique primero en la lista de dependencias (en la parte superior del bloque de dependencies).

    Para evitar conflictos con los identificadores de recursos más comunes, considera usar un prefijo o cualquier otro esquema de nombramiento coherente que sea exclusivo del módulo (o de todos los módulos del proyecto).

  • En las compilaciones de varios módulos, las dependencias JAR se tratan como dependencias transitivas

    Cuando se agrega una dependencia JAR a un proyecto de biblioteca que genera un AAR, el módulo de biblioteca procesa el JAR y lo empaqueta con su AAR.

    Sin embargo, si el proyecto incluye un módulo de biblioteca que un módulo de app consume, el módulo de app trata la dependencia JAR local de la biblioteca como una dependencia transitiva. En este caso, el JAR local es procesado por el módulo de la app que lo consume, y no por el módulo de la biblioteca. Esto tiene como objetivo acelerar las compilaciones incrementales producidas por cambios en el código de la biblioteca.

    Cualquier conflicto de recursos Java causado por dependencias JAR locales debe resolverse en el módulo de la app que consume la biblioteca.

  • 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 de Maps). En este caso, la app dependiente debe realizar compilaciones en un objetivo que incluya la biblioteca externa (por ejemplo, los complementos de las API de Google). También ten en cuenta que tanto el módulo de la biblioteca como la app dependiente deben declarar la biblioteca externa en sus archivos de manifiesto, en un elemento <uses-library>.

  • El valor de minSdkVersion del módulo de app debe ser igual o mayor que 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 admite el módulo de la app.

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

    Cuando compilas los módulos de app dependientes, se compilan los módulos de biblioteca en un archivo AAR y, luego, se agregan al módulo de la app. Por lo tanto, cada biblioteca tiene su propia clase R cuyo nombre corresponde 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.

  • Un módulo de biblioteca puede incluir su propio archivo de configuración ProGuard

    Si tienes un proyecto de biblioteca que usas para compilar y publicar un AAR, puedes agregar un archivo de configuración de ProGuard a la configuración de compilación de la biblioteca, y el complemento de Gradle para Android aplicará las reglas de ProGuard que hayas especificado. 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.

    Mediante la incorporación de un archivo ProGuard en el módulo de biblioteca, garantizas que los módulos de app que dependen de la biblioteca no tengan que actualizar manualmente los archivos ProGuard para usarla. Cuando se ejecute ProGuard en el módulo de la app de Android, usa las directivas del módulo de app y de la biblioteca. Por lo tanto, no debes ejecutar ProGuard solo en la biblioteca.

    Para agregar las reglas de ProGuard al proyecto de biblioteca, debes especificar el nombre del archivo con la propiedad consumerProguardFiles, dentro del bloque defaultConfig correspondiente al archivo build.gradle de la biblioteca. Por ejemplo, en el siguiente fragmento, se configura lib-proguard-rules.txt como archivo de configuración de ProGuard de la biblioteca:

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

    Sin embargo, si el módulo de biblioteca es parte de una compilación de múltiples módulos que se compilan en un APK y no se genera un AAR, debes ejecutar ProGuard solo en el módulo de la app que consuma la biblioteca. Para obtener más información sobre las reglas de ProGuard y su uso, consulta Cómo reducir el código y los recursos.

  • Probar un módulo de biblioteca es lo mismo que probar una app

    La principal diferencia es que se incluyen automáticamente la biblioteca y sus dependencias como dependencias del APK de prueba. Esto significa que el APK de prueba incluye no solo su propio código, sino también el AAR de la biblioteca y todas sus dependencias. Debido a que no hay una "app de prueba" separada, la tarea androidTest instala (y desinstala) solo el APK de prueba.

    Cuando se combinan varios archivos de manifiesto, Gradle sigue el orden de prioridad predeterminado y combina el manifiesto de la biblioteca en el manifiesto principal del APK de prueba.

Anatomía de un archivo AAR

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

  • /AndroidManifest.xml
  • /classes.jar
  • /res/
  • /R.txt
  • /public.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 compatibles con Android)
  • /proguard.txt
  • /lint.jar
  • /api.jar