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 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 ofrecen las siguientes funciones para las aplicaciones de Android:

  • 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.
  • Los archivos AAR pueden contener bibliotecas C/C++ para que los use el código C/C++ del módulo de la app.

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 la 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 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 para applicationId. Solo un módulo de aplicación de Android puede definir esto.
  3. En la parte superior del archivo, se mostrará lo siguiente:

    Groovy

    implementation project(path: ':example-library')
    

    Kotlin

      plugins {
          id("com.android.application")
      }
      

    Groovy

      apply plugin: 'com.android.application'

    Cámbialo por lo siguiente:

    Groovy

      apply plugin: 'com.android.library'
      

    Kotlin

      plugins {
          id("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 dependencias con el diálogo Project Structure

Cómo usar tu biblioteca desde el mismo proyecto

Para usar código de tu nueva biblioteca de Android en otra app u otro módulo de biblioteca dentro del mismo proyecto, agrega una dependencia a nivel de proyecto:

  1. Ve a File > Project Structure > Dependencies.
  2. Selecciona el módulo en el que usarás la biblioteca.
  3. En la pestaña Declared Dependencies, haz clic en y selecciona Module Dependency en el menú desplegable.

  4. En el diálogo Add Module Dependency, selecciona tu módulo de biblioteca.

    Cómo agregar una dependencia de módulo en el diálogo Project Structure

  5. Selecciona la configuración que requiere esta dependencia o elige "Implementación" si se aplica a todas las configuraciones y haz clic en Aceptar.

Studio editará el archivo build.gradle de tus módulos para agregar la dependencia del formulario:

implementation(project(path: ":example-library"))

Cómo usar tu biblioteca en otros proyectos

La forma recomendada de compartir dependencias (JAR y AAR) es con un repositorio de Maven, alojado en un servicio como Maven Central o con una estructura de directorio en tu biblioteca local. Para obtener más información sobre cómo usar repositorios de Maven, consulta Repositorios remotos.

Cuando se publica una biblioteca de Android en un repositorio de Maven, se incluyen los metadatos para que las dependencias de la biblioteca se incluyan en la compilación que las usa, lo que permite que se anule automáticamente el duplicado de la biblioteca si se utiliza en varios lugares.

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

  1. Ve a File > Project Structure > Dependencies.
  2. En la pestaña Declared Dependencies, haz clic en y selecciona Library Dependency en el menú desplegable.

  3. En el diálogo Add Library Dependency, usa el cuadro de búsqueda para buscar la biblioteca que quieres agregar. Este formulario busca los repositorios especificados en los archivos de compilación del proyecto en el bloqueo de repositories.

    Cómo agregar la dependencia de la biblioteca en el diálogo Project Structure

  4. Selecciona la configuración que requiere esta dependencia o elige “implementación” si se aplica a todas las configuraciones.

  5. Revisa el archivo build.gradle de tu app para confirmar una declaración similar a la siguiente (según la configuración de compilación que hayas seleccionado):

    implementation 'com.example:examplelibrary:1.0.0'

Cómo agregar tu AAR o JAR como una dependencia

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

  1. Ve a File > Project Structure > Dependencies.
  2. En la pestaña Declared Dependencies, haz clic en y selecciona Jar Dependency en el menú desplegable.

  3. En el diálogo Add Jar/Aar Dependency, primero ingresa la ruta de acceso a tu archivo .aar o .jar y, luego, selecciona la configuración a la que se aplica la dependencia. Si la biblioteca debería estar disponible para todas las configuraciones, selecciona la configuración de "implementación".

    Cómo agregar la dependencia AAR en el diálogo Project Structure

  4. Revisa el archivo build.gradle de tu app para confirmar una declaración similar a la siguiente (según la configuración de compilación que hayas seleccionado):

      implementation files('my_path/my_lib.aar')
    

Como alternativa, si ejecutas compilaciones de Gradle fuera de Android Studio, es posible importar una dependencia agregando una ruta de acceso a la dependencia en el archivo build.gradle de tu app. Por ejemplo:

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
    ...
}

Para obtener más información sobre cómo agregar dependencias de Gradle, consulta Cómo agregar dependencias de compilación.

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 en el directorio res/ de tu 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, debes 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 strings 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.

Cuando compilas 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 el tiempo de 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 ID de recurso específico en ambos módulos, se usará 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 con los ID 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). 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>.

  • 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 que 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 el sistema de compilación de Android Studio compila tu app, usa las directivas del módulo de app y de la biblioteca. Por lo tanto, no es necesario ejecutar un reductor de código en la biblioteca en un paso separado.

    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:

    Groovy

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

    Kotlin

    android {
        defaultConfig {
            consumerProguardFiles("lib-proguard-rules.txt")
        }
        ...
    }

    Sin embargo, si el módulo de biblioteca es parte de una compilación de varios módulos que se compila en un APK y no genera un AAR, debes ejecutar la reducción de código 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, ofuscar y optimizar tu app.

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

    La principal diferencia es que la biblioteca y sus dependencias se incluyen automáticamente 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 en sí es un archivo ZIP. La única entrada obligatoria es /AndroidManifest.xml.

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

  • /classes.jar
  • /res/
  • /R.txt
  • /public.txt
  • /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
  • /prefab/ para exportar bibliotecas nativas