Import local gradle projects as modules

Dima Brody
3 min readApr 15, 2024

--

Sometimes, the following situation occurs: you develop a functionality in a modular app and realize that some utility modules can be repurposed as libraries to share the codebase among your projects. There are various ways to achieve this.

Prebuilt library approaches

The first three approaches involve using a prebuilt version of your library and distributing it in various ways:

  1. Build your library as a .jar or .aar (Java/Android Archive File) and place it in your ./app/libs folder. Then, you can use it as an implemented library.
  2. Add the .jar or .aar file directly using the Project Structure window in Android Studio, and add the library as a new Module Dependency.
  3. Use a remote repository that hosts your library, such as JitPack or Maven Central. This approach is beneficial for IT companies and is popular in backend microservices, where each microservice utilizes a library with common elements, typically stored in repositories like npm and implemented by each service.

There is a helpful StackOverflow article discussing these and other approaches. Even though jcenter.bintray repository is already deprecated, you can find good applications of third approach on the internet.

A disadvantage of using prebuilt libraries is that once they are built, they cannot be modified. While this rigidity is beneficial for more stable projects, it poses a challenge during active development phases when frequent updates to the library may be necessary. How can developers avoid repeatedly rebuilding the same library?

Use library which is connected directly, not as a build

There are two scenarios:

  1. Fetching separate modules from an external library
  2. Connecting to the entire project as an entire Gradle build — this is the recommended approach.

1. Fetch separate modules from an external library

To include a local module from another directory into your main Gradle project and use it as a dependency, follow these steps:

1. Update the settings.gradle File. First, you need to inform Gradle about the module by including it in your project. Edit your settings.gradle file to include the module and specify its directory:

2. Add the Module as a Dependency. After including the module in your settings file, you can now add it as a dependency in your build.gradle file. This will allow you to use the module's functionality within your main project.

A significant drawback of the approach described is that plugins and libraries loaded globally for the implemented project may not be detected. This occurs because the method involves including only one library, effectively isolating the code from its broader environment. The next approach aims to address this issue by ensuring better integration of globally loaded resources.

2. Connect the project as an entire Gradle build (Recommended)

You can include an entire build by using the includeBuild() function. This function was specifically designed to facilitate the creation of Composite Builds. A composite build is similar to a Gradle multi-project build, except that instead of including subprojects, entire builds are included.

You can use includeBuild("../developed-project/mylibrary") directly but the next problem occurs: gradle failes to resolve our library when we try to implement it.

To overcome this, we have to specify our dependency name directly:

Now, our dependency is ready to be implemented:

You can use your external libraries with modules as dependencies in this way.

P.S: There is also an example of code written above using the .kts DSL:

Conclusion

Concluding the article, the choice between using prebuilt libraries and directly connecting to source projects depends largely on your project’s stage and specific needs. For more stable, less frequently updated projects, using prebuilt libraries might be the most efficient approach. However, for projects under active development where frequent changes are common, using a direct project connection — especially through a composite build approach — provides flexibility and ease of updates, ensuring that all components stay synchronized without the need to rebuild and redeploy libraries continually. This adaptability is crucial for agile development environments where quick iterations and adaptations are necessary.

--

--

No responses yet