How to create an Android Library Jar with gradle without publicly revealing source code?
Note: The answer has been edited. Please see the 07/28/2014 update below.
Here is a solution I ended up coming up with. There may be a better way available, but I have not found it yet.
android { compileSdkVersion 18 buildToolsVersion "18.0.1" defaultConfig { minSdkVersion 10 targetSdkVersion 18 } sourceSets { main { java { srcDir 'src/main/java' } resources { srcDir 'src/../lib' } } }}task clearJar(type: Delete) { delete 'build/libs/ProjectName.jar'}task makeJar(type: Copy) { from('build/bundles/release/') into('build/libs/') include('classes.jar') rename ('classes.jar', 'ProjectName.jar')}makeJar.dependsOn(clearJar, build)
Running gradlew makeJar
creates a ProjectName.jar
in the build/libs
directory. The structure of this jar is as follows:
ProjectName.jar \- lib | \- armeabi | \- libNativeFirst.so | \- libNativeSecond.so \- com \- package \- sdk \- PackageSDK.class
This is the exact result I needed. I am now able to use ProjectName.jar
successfully in other projects.
EDIT: While I am able to use the resulting jar in projects within Android Studio, I cannot do so in projects created in ADT due to a warning about native code being present inside a jar file. Supposedly there is a flag to turn off this check in settings, but it does not function correctly. Thus, if you want to create a library that uses native code, those using ADT will have to manually copy the armeabi directory into libs/.
07/28/2014 Update:
As of Android Studio 0.8.0, Gradle output directories have been changed and the configuration outlined above will not work. I have changed my configuration to the following:
task clearJar(type: Delete) { delete 'build/outputs/ProjectName.jar'}task makeJar(type: Copy) { from('build/intermediates/bundles/release/') into('build/outputs/') include('classes.jar') rename ('classes.jar', 'ProjectName.jar')}
IMPORTANT: Please note that ProjectName.jar
will now be placed into build/outputs/
and NOT into build/libs/
.
Just to add a slight alternative to @BVB's answer (although heavily based on it) here's what I had to do to output a jar myapp-api.jar
which was for a Java only project that dealt with rest API interaction. It's dependant on Android.jar hence the need to use apply plugin: 'com.android.application'
rather than just apply plugin: 'java'
Calling ./gradlew build jar
from the myJavaAPIProject to build and generate the .jar to myJavaAPIProject/build/libs/myapp-api.jar
build.gradle
//Even though this is a Java project, we need to apply the android plugin otherwise it cannot find the SDK/android.jar and so cannot compileapply plugin: 'com.android.application'dependencies { //this ensures we have gson.jar and anything else in the /lib folder compile fileTree(dir: 'lib', include: '*.jar')}repositories { mavenCentral()}android{ compileSdkVersion 21 buildToolsVersion "21.0.1" defaultConfig { minSdkVersion 10 targetSdkVersion 21 } sourceSets { main { java { //points to an empty manifest, needed just to get the build to work manifest.srcFile 'AndroidManifest.xml' //defined our src dir as it's not the default dir gradle looks for java.srcDirs = ['src'] } } } //enforce java 7 compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 }}//Actually created the .jar filetask jar(type: Jar) { //from android.sourceSets.main.java from 'build/intermediates/classes/release/' archiveName 'myapp-api.jar'}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><!-- this is a dummy file needed to ensure gradle validates and builds ok --><manifest package="com.myapp.android" />