8

Like many others, I am trying to generate a single AAR file from my multi-modules Android project.

According to this post, it is not currently supported by the Android team because of various limitations (res & dependencies management, manifest merging, ...).

I am trying to come up with my own solution that will fits my needs. I know that I don't have duplicated resources and external dependencies (like the Support Libraries) are provided by the people using my lib.

My structure is similar to this:

/root
|- lib1
|- lib2
|- lib3

In order to achieve my goal, I created one more library module, named distribute, that will include all the others modules. I can then share the generated distribute.aar file.

/root
|- lib1
|- lib2
|- lib3
|- distribute

This is the build.gradle file of the distribute module:

apply from: '../common.gradle' // This simply configure properties shared accross all modules
apply plugin: 'com.android.library'

def allModules = rootProject.allprojects.collect { it.name } - [rootProject.name, name]
def whiteLabelDependencies = [
        whiteLabel1: allModules - ['lib2'],
        whiteLabel2: allModules,
]

android {
    def buildTypeNames = buildTypes.collect { it.name }
    def whiteLabelTypes = productFlavors.findAll { 'type'.equals(it.dimension) }.collect { it.name }

    whiteLabelDependencies.each { whiteLabel ->
        def modules = whiteLabel.value
        def whiteLabelName = whiteLabel.key

        whiteLabelTypes.each { whiteLabelType ->
            def productFlavor = whiteLabelName + whiteLabelType.capitalize()

            buildTypeNames.each { buildType ->
                def sourceSet = productFlavor + buildType.capitalize()
                def folders = ['main', whiteLabelName, whiteLabelType, productFlavor, whiteLabelName + buildType.capitalize(), sourceSet]

                android.sourceSets.maybeCreate(sourceSet)
                android.sourceSets.getByName(sourceSet) {
                    assets.srcDirs = getPathsList(modules, folders, 'assets')
                    java.srcDirs = getPathsList(modules, folders, 'java')
                    res.srcDirs = getPathsList(modules, folders, 'res')
                    resources.srcDirs = getPathsList(modules, folders, 'resources')
                }
            }
        }
    }
}

afterEvaluate {
    whiteLabelDependencies.each { whiteLabel ->
        def assembleTask = rootProject.tasks.getByPath(":${name}:assemble${whiteLabel.key.capitalize()}")
        assembleTask.dependsOn whiteLabel.value.collect { ":${it}:assemble${whiteLabel.key.capitalize()}" }
    }
}

dependencies {
    whiteLabelDependencies.each { whiteLabel ->
        whiteLabel.value.each {
            "${whiteLabel.key}Compile" project(path: ":${it}", configuration: project.whiteLabelConfigurationName)
        }
    }
}

def List<File> getPathsList(List<String> modules, List<String> folders, String sourceType) {
    return modules.collect { module ->
        folders.collect { folder ->
            new File("${rootProject.rootDir}/${module}/src/${folder}/${sourceType}")
        }.findAll {
            it.exists()
        }
    }.flatten()
}

This seem to be almost working, except that at runtime, the application crash because it can not find the R class of each libx module, only the one of the distribute module. Is there a way to force Gradle to include the R class of each module.

I know that the file for each module is generated in $module/build/generated/source/r/$whiteLabel/$buildType/$package/$module/R.java, but I don't know how to include it and prevent duplicated classes (each module can depends on an other one).

Community
  • 1
  • 1
Gaëtan
  • 11,912
  • 7
  • 35
  • 45
  • Are `libX/R.class` classes merged into a single `distribute/R.class`? – naXa stands with Ukraine Jun 28 '16 at 10:13
  • No. Each `lib` has its own `R` class, because each module has its own package (a limitation/requirement of Android Gradle Plugin I think). The final `distribute/R` class contains all the necessary field, but each module import its own `R` class. – Gaëtan Jun 28 '16 at 12:19
  • So (I think) you should rewrite imports in all modules to `distribute/R` during build. – naXa stands with Ukraine Jun 28 '16 at 13:19
  • I tried to do that by using the Transform API, but I didn't find any proper documentation nor example of how to change import at compile time. – Gaëtan Jun 28 '16 at 14:27
  • @Gaëtan, i am facing similar kind of problem. Please tell me if you got succeed in solving this problem, how you made it?? Any help would be appreciated. – Naseeb Sheoran Sep 27 '16 at 14:10
  • Possible duplicate of [Android Studio how to package single AAR from multiple library projects?](https://stackoverflow.com/questions/20700581/android-studio-how-to-package-single-aar-from-multiple-library-projects) – norbDEV Jan 05 '18 at 09:30

0 Answers0