Friday, December 29, 2017

How to build 1 jar from 3 sub-modules by using gradle

Leave a Comment

I have:

  • Android Studio 3
  • gradle 4.1
  • gradle tools 3: classpath 'com.android.tools.build:gradle:3.0.1'

When I had one module and used gradle tools 2, I used:

task makeJar(type: Copy) {     def releaseFolder = new File('build/intermediates/bundles/release/')     if (releaseFolder.exists()) {         from('build/intermediates/bundles/release/')     } else {         from('build/intermediates/bundles/default/')     }     into('build/outputs/jar/')     include('classes.jar')     rename ('classes.jar', 'MY-Android-SDK.jar') } 

Now have 3 modules:

              MainModule (com.my)                  /   \ (com.my.m1) Module1   Module2 (com.my.m2) 

I want to create MY-Android-SDK.jar file from all 3 modules.

So far I will be able to create 3 jar files per module and somehow merge them but I believe its not right way to do that.

Any ideas?

1 Answers

Answers 1

First of all, if you are creating android libraries, create AARs, not JARs. AAR files follow the android SDK structure and can have manifest files, and therefore, require permissions, and xml resources, among other things.

Second, if you are creating a framework from several different modules (a pretty reasonable approach in fact!), you should create different artifacts (AAR/JAR files). That makes easier to handle transitive dependencies, SDK level conflicts, consuming only what you need (there will be cases when you don't need half of your SDK and in that case discarding a few entries in the gradle files is way easier than fiddling with proguard to delete all the unused classes), providing alternative implementations or pluggable systems (for example, you create a contract module for, let's say, DFP, and a double click module. Then, by Inversion of Control, you fill the contract using double click, next month, they ask you to replace double click with amazon ads. You create a module with amazon ads following the contract module and replace the injected double click reference by amazon.)

Regardless of that, remember transitivity. Depending on how you bring your dependencies, everything can be added to the path by using a single dependency in the build.gradle file. If you use 'api':

api 'com.myname:moduleX:xxx' 

In module com.myname:moduleY, moduleX will be in the path as well. Use the Gradle maven plugin for creating the artifacts in the first place. That will allow you to create an android AAR file using the "install" task and will deploy it to your local maven repo (mavenLocal() in gradle). If you include all the submodules using "api", they will be added to the path. I don't recommend doing that, instead, import only what's necessary in each module and create separate AAR files for each module and consume them in your apps.

Now, if for some reason, you need to create a fat/Uber JAR, well, that process is called "shading". So, you'll need a shade plugin for gradle. Fortunately, there's a few. Just pick the best for your case (or use maven, and the maven shade plugin). Regardless, as someone with some experience developing libraries and frameworks, keep your modules as atomic and separate as possible. Lastly, if you need a working example for the gradle maven plugin, try this, it's old, but works as an example. good luck!

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment