Publish multiple Android libraries as one with Fused Library

In projects with many modules, it can be challenging to distribute Android Libraries to your users while trying to maintain a clear project structure. In many cases, many more libraries need to be published than intended.

The Fused Library plugin bundled with Android Gradle Plugin assists with packaging multiple Android Library modules into a single publishable Android Library. This lets you to modularise your library's source code and resources within your build as you see fit, while avoiding exposure of your project's structure once distributed.

Distributing as a single library can have the following benefits:

  • Simplified dependencies: replaces multiple library dependencies with a single AAR, streamlining project setup and version management for your users
  • Reduced library size: may improve code shrinking, leading to smaller AARs
  • Improved security: can offer better control over the internal implementation details of published libraries

Create a fused library

To build a fused library, you have to create a new Android module, add dependencies, and then publish the fused library.

Add a new fused library module

To use the plugin, you must add a new Android module to your project:

In this example, the fused library module will be called myFusedLibrary.

  1. Append include(':myFusedLibrary') to the settings.gradle.kts file.
  2. Add android-fusedlibrary = { id = "com.android.fused-library", version.ref = "agp" } under the [plugins] section in the gradle/libs.versions.toml file.
  3. Add alias(libs.plugins.android.fusedlibrary) apply false in the plugins block in the top level build.gradle.kts file.
  4. To create the myFusedLibrary module, create a new directory called myFusedLibrary (right-click 'My Application' > New > Directory).
  5. Create a build.gradle.kts file in the myFusedLibrary module (right-click the myFusedLibrary module > New > File).

  6. Paste the following into the myFusedLibrary/build.gradle.kts file:

Kotlin

plugins {
    alias(libs.plugins.android.fusedlibrary)
    `maven-publish`
}

androidFusedLibrary {
    namespace = 'com.example.myFusedLibrary'
    minSdk = 21
}

dependencies { }

Groovy

plugins {
    id 'fused-library'
}

androidFusedLibrary {
    namespace 'com.example.myFusedLibrary'
    minSdk 21
}

dependencies {

}

Add dependencies

The core functionality of the fused library is to bundle dependencies. The plugin supports adding local project dependencies and external libraries. To specify dependencies to be packaged, use the include configuration. Transitive dependencies are not packaged.

For example:

Kotlin

dependencies {
    include(project(':image-rendering'))
    include('mycoolfonts:font-wingdings:5.0')
}

Groovy

dependencies {
    include project(':image-rendering')
    include 'mycoolfonts:font-wingdings:5.0'
}

Publish your fused library

You should familiarize yourself with publishing an Android library before publishing a fused library. Publishing a fused library is similar to publishing an Android Library, however there are some key differences that you must consider to publish the fused library correctly:

  • The Maven Publish Plugin must also be applied to any module that has the Fused Library plugin applied.
  • The publication must inherit from the fusedLibraryComponent because this provides the required dependencies needed to compile the fused library artifact.

Here's an example of a publications configuration:

Kotlin

plugins {
    alias(libs.plugins.android.fusedlibrary)
    `maven-publish`
}

androidFusedLibrary {  }

dependencies {  }

publishing {
    publications {
        register('release') {
             groupId = "my-company"
             artifactId = "my-fused-library"
             version = "1.0"
             from(components['fusedLibraryComponent'])
        }
    }
}

Groovy

plugins {
    id 'fused-library'
    id `maven-publish`
}

androidFusedLibrary {  }

dependencies {  }

publishing {
    publications {
        release(MavenPublication) {
            groupId = "my-company"
            artifactId = "my-fused-library"
            version = "1.0"
            afterEvaluate {
            from components.fusedLibraryComponent
        }
    }
}

Publish your fused library for testing

You should test depending on a published fused library from an Android app or Android library. The recommended method is to publish to the fused library and its project dependencies to a local Maven repository.

To publish the fused library artifacts to a local repository, define a configuration similar to the following:

Kotlin

plugins {
    alias(libs.plugins.android.fusedlibrary)
    'maven-publish'
}

repositories {
    maven {
        name = 'myLocalRepo'
        url = uri(layout.buildDirectory.dir('myLocalRepo'))
    }
}

Groovy

plugins {
    id 'fused-library'
    id 'maven-publish'
}

repositories {
    maven {
        name 'myLocalRepo'
        url layout.buildDirectory.dir('myLocalRepo')
    }
}

Upload your fused library

To distribute your fused library, see Upload your library.

Behavior and safeguards

Combining Android Libraries have intricacies that can make it challenging for the plugin to reason about priorities. For example, two libraries with the same classpath will cause a build failure when fusing the library. Resource merging will consider the order of dependencies specified when selecting a resource with the same name in different libraries.

  • Fused libraries can only be published as an Android library artefact AAR in order to be added as a dependency.
  • Fusing libraries that use data binding isn't supported.
  • You can't fuse multiple build types and product flavors within a single fused library. Create separate fused libraries for different variants.

To balance the amount of configuration needed and ease of use, the plugin will either fail the build on ambiguous conflicts or use heuristics when fusing artifacts. The details of how artifacts are fused are found in the following table:

Type Behavior
Classes Libraries with the same classpath will cause a build failure when fusing the library.
Android Resources Resource merging will consider the order of dependencies specified when selecting a resource with the same name in different.
AAR Metadata AAR metadata versions are merged by prioritizing the highest value from each dependency library. There is a DSL provided to override these values.

Kotlin

 androidFusedLibrary { aarMetadata { minCompileSdk = 21 minCompileSdkExtension = 1 } }
Java Resources Java resource files in multiple libraries with identical paths is not permitted and will result in a build failure.

Known issues

Fused Library is a new plugin and there are known issues that are being worked on to fulfill all use cases.

  • lint.jar files aren't included in the fused AAR
  • Adding file dependencies on other .aar files
  • No support for fusing RenderScript and Prefab artifacts

Understand the dependencies of a fused library

The fused library has no sources and effectively uses Android libraries as its only source, it's important to understand what comes from where. To list the dependencies that are merged into the resultant artifact and the dependencies needed to build the artifact, run the gradle :report task on the fused library. The tasks generates a JSON report that is saved in the build/reports directory of the fused library.

For additional information related to internal plugin dependencies, run the gradle :dependencies task to view the state of plugin configurations.