My current task is to separate one of the application screens as a library so that another application can have it and keep all the functionality of the screen
The screen consists of 3 modules of clean architecture: Ui
, Domain
& Data
and it works fine in the application. Also, we have some utills modules in UI
& Data
layers.
Our modules have the com.android.library
plugin
How can I create such feature as a library without changing the current architecture of the project (i.e. keep the current modules intact)
And I also think that there will be problems combining the DI
code of the library and the client code. (We use Koin
). But now it is not big problem.
Project look like
root
|-- app
|-- build.gradle
|-- src
|-- CombineFeatures
|-- ui
|-- feature1
|-- build.gradle
|-- src
|-- Feature1UICode
|-- domain
|-- feature1
|-- build.gradle
|-- src
|-- Feature1DomainCode
|-- data
|-- feature1
|-- build.gradle
|-- src
|-- Feature1DataCode
|-- settings.gradle
I tried to build the AAR
library from the UI
module using the gradle assemble
task, however, it did not have the rest of the clean layers and denepndecies from project (like material3
etc.) , which is why I got java.lang.NoClassDefFoundError: Failed resolution of...
.
In this case, I could only invoke the functions of the imported module.
Can I combine several AAR
files into one? As variant, I can try use fat-aar-lib -> Building aar library from multimodule project. But it seems like not modern solution.
We do not consider the option of moving the functionality to a separate project and repository, because it will be difficult to maintain in future
Also, earlier we tried to make composite builds, but it was very slow and forced us to have all the source code (of the project) locally, so we abandoned this option
As a prod solution, option 2 was preferred, because it would allow us to connect individual functions without depending on other unnecessary ones
buildSrc
plugins {
`maven-publish`
}
afterEvaluate {
publishing {
publications {
register<MavenPublication>("release") {
from(components.findByName("release"))
groupId = project.hierarchy.concatGroup()
artifactId = project.name
version = libs.versions.versionName.get()
}
}
repositories {
maven("...") {
credentials {
username = getLocalProperty("MAVEN_USERNAME")
password = getLocalProperty("MAVEN_PASSWORD")
}
}
}
}
}
And some utils in buildSrc
val Project.hierarchy get(): List<Project> =
generateSequence(this, Project::getParent).toList().reversed()
fun List<Project>.concatGroup(): String {
return dropLast(1).joinToString(".") { it.name }
}
Thus, we get the name of the dependencies in the repository the same as the name of the modules tree of your project
And don't forget to connect your maven repository to the gradle project
Then you can connect this plugin to the modules you want to put into the repository (or another plugin as in my case)
plugins {
id("com.android.library")
kotlin("android")
/* ... */
id("publishing-plugin")
}
After that, you can call the publishAndroidReleasePublicationToMavenRepository
or publishReleasePublicationToMavenRepository
task, depending on the configuration of your project (KMP
or Android
).
After that, all modules to which the plugin has been applied will be uploaded to the specified maven repository.
your-app-feature = { group = "YourProject.features.feature", name = "feature", version.ref = "your-proj-version" }
After a year from the previously found solution.
I Found an article on a Russian resource on this topic using a more modern version of the fat-aar solution - Grease
It may be worth considering switching to such a solution