I want to have a gradle "project" that creates a jar using a custom task (doesn't use any of the gradle java plugins). What is the proper way to construct the build.gradle so that I can depend on it in my android app's gradle project?
More Details:
Currently my jar file is being created in a cmake project that I call from gradle.
I want to have a proper build.gradle file that calls my cmake command then uses the resulting jar as the artifact. Then I would like to be able to simply add "compile project(':mylib') from my android project's build.gradle.
you can make a jar task like:
task myJar(type:Jar) {
archiveName='my.jar'
from sourceSets.main.output
include 'foo/com/**/*', 'bar/com/**/*'
}
Related
I have a library with all the source files inside of it. I need to compile this library into an .aar file, but I can't seem to import it into a module or project. There is no .idea folder within this library.
How can I create an .aar file out of this?
If the library is in your project with the source, then it is already compiled each time you run. Look under <your_lib> -> build -> outputs -> aar. There you will have an .aar for each build type you have. i.e. debug and release
It may be simplest to create a new AAR library module in Android Studio and then copy the source and resources for your library into the new module. To do this select File > New > New Module... > Android Library.
However, if you already have an Android project and you just want to alter the build to generate the project as an AAR library rather than an application, you can change the plugin used in the Gradle build script.
Alter the apply plugin line from:
apply plugin: ‘com.android.application’
to:
apply plugin: ‘com.android.library’
In Eclipse, you can create a project jar with its required dependencies in an adjacent sub-folder by doing ...
Export->Java->Runnable JAR file
Select Library handling option: Copy required libraries into a sub-folder next to the generated JAR
Is there a way to do this with the Gradle?
PS: I am working on gradle 2.2.1
You can create a Gradle task for copying, like so:
task copyLibs(type: Copy) {
from('path/to/dir/with/lib/jars/')
into('path/to/subfolder/next/to/generated/jar/')
include('names.jar','of.jar','jars.jar','to.jar','copy.jar')
}
copyLibs.dependsOn(build)
Edit:
task combinedJar(type: Jar) {
from zipTree("path/to/generated.jar")
from "path/to/subfolder/next/to/generated/jar/"
}
combinedJar.dependsOn(copyLibs)
Run via gradlew copyLibs. You can make the task depend on the build task that builds your project.
Note that you may have to also create the path/to/subfolder/next/to/generated/jar/ in the task.
I have a command line program that, depending on a set of source files, generates a jar file that I want to use in my Android gradle build (A). This command line program simply stores a jar file in a directory on the disk.
How can I create a new gradle project (B) that runs my command line program (inside of a gradle multi-project setup) that the Android Gradle project(A) will depend on: in other words, if the sources for B change, it should rebuild!
Note:
Project B is neither a Android library project nor is it a java project. It simply runs a program via command line that happens to store a jar file on the file system.
You could do this by creating your own custom task(s) in project B to execute your program which generates a JAR. Be sure to declare your inputs/outputs properly so Gradle knows how to handle dependencies for the task:
task buildProjB {
inputs.file file('my_source_file.name')
ext.dest = new File(buildDir, "libs")
outputs.dir ext.dest
doLast {
// Run your program and put output in "libs" subdir
}
}
tasks.whenTaskAdded { theTask ->
if (theTask.name.contains("assemble")) {
theTask.dependsOn "buildProjB"
}
}
Note that the buildProjB task gets "hooked" to any of the assemble tasks. You will likely need to do this or to one of the build tasks in order for it to be built properly as part of the normal Android app build.
In your project A settings.gradle, make project B part of the build:
include ':projectA', ':projectB'
In your project A build.gradle file, make project B a dependency:
dependencies {
...
compile project(':projectB')
}
This is assuming you have project B (module in Android Studio terms) beneath the top level Android Studio project, so at the same level as project A.
I need a clear example of how to extend an Android Gradle project with an arbitrary project.
By arbitrary I mean that it can't just use the 'java' plugin since it doesn't support buildTypes to my knowledge. I am currently using an 'ant' task for this, which has two targets for debug and release, however I don't see how to tie it into an Android project.
Assume that your dependent project must build pure Java source in two ways:
debug build that produces a debug version in 'purejava.jar'
release build that produces a release version in 'purejava.jar'
The jar 'purejava.jar' is to be placed such that the Android project (could be a multi-project) is able to reference it at compile time, and it must therefore be the correct build to support both the debug and release configurations of the Android project.
How should this be tackled?
Since I am new to Android Studio and Gradle, I don't have a clear idea of how to manipulate extensions generated by the Android plugin, which are not available until after project evaluation.
How should the Android project be made dependent on this pure java project?
If it weren't for the fact that you need debug and release versions of your library, then your Android app could depend on a plain Java module just fine -- you could set up the library with the java plugin and put a compile project statement in the app's dependencies and it would work fine.
However, the Java plugin is never going to understand Android's notion of build types (unless GradleWare adds it at some point), so you can't propagate that to your Java modules. You could set up your plain Java project as an Android library and use the android-library plugin (you'll have to dummy out the manifest and other Android-specific stuff it expects to see in Android libraries), but you'll run into a different problem: https://code.google.com/p/android/issues/detail?id=52962 is a bug that reports that the build type is not propagated to library modules.
Until that bug is fixed, or if you're unwilling to make your plain Java library an android library, I think your only approach is to make two different versions of your library, compile them to different jar files, and selectively pull in dependencies.
This is my answer, with following project structure:
MyProject
-- MyAndroidLib
-- JarProject
This represents the gradle top project 'MyProject' which has a sub-project 'MyAndroidLib' which is dependent on a pure java project 'JarProject' which is built with different code for debug than for release builds.
I'll take advantage of Android's 'debugCompile' and
'releaseCompile' configurations. In the Android sub-project ('MyAndroidLib') that is dependent on the jars, add following lines to the dependencies:
//MyAndroidLib build.gradle
def jarProject = project(':MyProject:MyAndroidLib:JarProject')
def jarPath = pcfProject.projectDir.toString()
dependencies {
....
compile jarProject
debugCompile files(jarPath + '/' + jarProject.debugJarName)
releaseCompile files(jarPath + '/' + jarProject.releaseJarName)
}
The 'jarProject' def is defined to simplify accessing it from the MyAndroidLib project. (If you know a better way ...)
The main point of this is to define a separate debug and release jar path for the 'debugCompile' and 'releaseCompile' configurations. The 'debugJarName' and 'releaseJarName' are defined in a gradle.properties file for the JarProject as follows:
//JarProject gradle.properties
debugJarName=jarproject_d.jar
releaseJarName=jarproject_r.jar
In the gradle file for JarProject define a task that builds BOTH jar files named by this properties file. In my case, they are built right in the project folder by the 'compile' target of an ant build file located in that project.
//JarProject build.gradle
apply plugin: 'java'
project.ext.set("debugJar", file(projectDir.toString() + "/" + debugJarName))
project.ext.set("releaseJar",file(projectDir.toString() + "/" + releaseJarName))
task buildJars(type: Exec) {
description 'Build the debug and release jars for the JarProject'
outputs.files debugJar,releaseJar
commandLine 'ant', 'compile'
}
task compileJava.dependsOn('buildJars')
artifacts {
buildJars
}
clean.dependsOn('cleanBuildJars')
clean << {
exec {
commandLine 'ant', 'clean'
}
}
I took advantage of the 'java' plugin since it defines a 'compile' interface, and I haven't figured out how to build this from scratch, or even from the 'base' plugin. This project takes advantage of the automatic 'cleanBuildJars' task created because I defined the outputs in 'buildJars' task. This is necessary in order to have them built as needed. I probably need to define the 'inputs' too, since if they change ...
If anyone sees how my first stumblings in the gradle/Android world can be improved, pls. add comments as needed.
I have downloaded some library sources and would like to export it as a Jar file using
Android Studio. Is there a way to export to jar file using Android studio ?
edit:
The library I want to export as jar is an Android library.
It's called "StandOut" and can be downloaded from GitHub.
https://github.com/pingpongboss/StandOut
It is not possible to export an Android library as a jar file. It is possible, however, to export it as aar file. Aar files being the new binary format for Android libraries. There's info about them in Google I/O, the New Build System video.
First, build the library in Android Studio or from command line issuing gradle build from your library's root directory.
This will result in <yourlibroot>/libs/build/yourlib.aar file.
This aar file is a binary representation of your library and can be added to your project instead of the library as a dependency project.
To add aar file as a dependency you have to publish it to the maven central or to your local maven repository, and then refer the aar file in your project's gradle.build file.
However, this step is a bit convoluted. I've found a good explanation how to do so here:
http://www.flexlabs.org/2013/06/using-local-aar-android-library-packages-in-gradle-builds
I was able to build a library source code to compiled .jar file, using approach from this solution:
https://stackoverflow.com/a/19037807/1002054
Here is the breakdown of what I did:
1. Checkout library repository
In may case it was a Volley library
2. Import library in Android Studio.
I used Android Studio 0.3.7. I've encountered some issues during that step, namely I had to copy gradle folder from new android project before I was able to import Volley library source code, this may vary depending on source code you use.
3. Modify your build.gradle file
// If your module is a library project, this is needed
//to properly recognize 'android-library' plugin
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.3'
}
}
apply plugin: 'android-library'
android {
compileSdkVersion 17
buildToolsVersion = 17
sourceSets {
main {
// Here is the path to your source code
java {
srcDir 'src'
}
}
}
}
// This is the actual solution, as in https://stackoverflow.com/a/19037807/1002054
task clearJar(type: Delete) {
delete 'build/libs/myCompiledLibrary.jar'
}
task makeJar(type: Copy) {
from('build/bundles/release/')
into('build/libs/')
include('classes.jar')
rename ('classes.jar', 'myCompiledLibrary.jar')
}
makeJar.dependsOn(clearJar, build)
4. Run gradlew makeJar command from your project root.
I my case I had to copy gradlew.bat and gradle files from new android project into my library project root.
You should find your compiled library file myCompiledLibrary.jar in build\libs directory.
I hope someone finds this useful.
Edit:
Caveat
Althought this works, you will encounter duplicate library exception while compiling a project with multiple modules, where more than one module (including application module) depends on the same jar file (eg. modules have own library directory, that is referenced in build.gradle of given module).
In case where you need to use single library in more then one module, I would recommend using this approach:
Android gradle build and the support library
Since Android Studio V1.0 the jar file is available inside the following project link:
debug ver: "your_app"\build\intermediates\bundles\debug\classes.jar
release ver: "your_app"\build\intermediates\bundles\release\classes.jar
The JAR file is created on the build procedure,
In Android Studio GUI it's from Build->Make Project and from CMD line it's "gradlew build".
Include the following into build.gradle:
android.libraryVariants.all { variant ->
task("generate${variant.name}Javadoc", type: Javadoc) {
description "Generates Javadoc for $variant.name."
source = variant.javaCompile.source
ext.androidJar = "${android.plugin.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
classpath = files(variant.javaCompile.classpath.files) + files(ext.androidJar)
}
task("javadoc${variant.name}", type: Jar) {
classifier = "javadoc"
description "Bundles Javadoc into a JAR file for $variant.name."
from tasks["generate${variant.name}Javadoc"]
}
task("jar${variant.name}", type: Jar) {
description "Bundles compiled .class files into a JAR file for $variant.name."
dependsOn variant.javaCompile
from variant.javaCompile.destinationDir
exclude '**/R.class', '**/R$*.class', '**/R.html', '**/R.*.html'
}
}
You can then execute gradle with: ./gradlew clean javadocRelease jarRelease which will build you your Jar and also a javadoc jar into the build/libs/ folder.
EDIT: With android gradle tools 1.10.+ getting the android SDK dir is different than before. You have to change the following (thanks Vishal!):
android.sdkDirectory
instead of
android.plugin.sdkDirectory
I was able to export a jar file in Android Studio using this tutorial:
https://www.youtube.com/watch?v=1i4I-Nph-Cw
"How To Export Jar From Android Studio "
I updated my answer to include all the steps for exporting a JAR in Android Studio:
1) Create Android application project, go to app->build.gradle
2) Change the following in this file:
modify apply plugin: 'com.android.application' to apply plugin: 'com.android.library'
remove the following: applicationId, versionCode and versionName
Add the following code:
// Task to delete old jar
task deleteOldJar(type: Delete){
delete 'release/AndroidPlugin2.jar'
}
// task to export contents as jar
task exportJar(type: Copy) {
from ('build/intermediates/bundles/release/')
into ('release/')
include ('classes.jar')
rename('classes.jar', 'AndroidPlugin2.jar')
}
exportJar.dependsOn(deleteOldJar, build)
3) Don't forget to click sync now in this file (top right or use sync button).
4) Click on Gradle tab (usually middle right) and scroll down to exportjar
5) Once you see the build successful message in the run window, using normal file explorer go to exported jar using the path: C:\Users\name\AndroidStudioProjects\ProjectName\app\release
you should see in this directory your jar file.
Good Luck :)
Here's yet another, slightly different answer with a few enhancements.
This code takes the .jar right out of the .aar. Personally, that gives me a bit more confidence that the bits being shipped via .jar are the same as the ones shipped via .aar. This also means that if you're using ProGuard, the output jar will be obfuscated as desired.
I also added a super "makeJar" task, that makes jars for all build variants.
task(makeJar) << {
// Empty. We'll add dependencies for this task below
}
// Generate jar creation tasks for all build variants
android.libraryVariants.all { variant ->
String taskName = "makeJar${variant.name.capitalize()}"
// Create a jar by extracting it from the assembled .aar
// This ensures that products distributed via .aar and .jar exactly the same bits
task (taskName, type: Copy) {
String archiveName = "${project.name}-${variant.name}"
String outputDir = "${buildDir.getPath()}/outputs"
dependsOn "assemble${variant.name.capitalize()}"
from(zipTree("${outputDir}/aar/${archiveName}.aar"))
into("${outputDir}/jar/")
include('classes.jar')
rename ('classes.jar', "${archiveName}-${variant.mergedFlavor.versionName}.jar")
}
makeJar.dependsOn tasks[taskName]
}
For the curious reader, I struggled to determine the correct variables and parameters that the com.android.library plugin uses to name .aar files. I finally found them in the Android Open Source Project here.
We can export a jar file for Android library project without resource files by Android studio. It is also requirement what I met recently.
1. Config your build.gradle file
// Task to delete old jar
task clearJar(type: Delete){
delete 'release/lunademo.jar'
}
// task to export contents as jar
task makeJar(type: Copy) {
from ('build/intermediates/bundles/release/')
into ('build/libs/')
include ('classes.jar')
rename('classes.jar', 'lunademo.jar')
}
makeJar.dependsOn(clearJar, build)
2. Run gradlew makeJar under your project root
You will see your libs under dir as build/libs/ if you are luckily.
============================================================
If you met issue as "Socket timeout exception" on command line as below,
You can follow this steps to open Gradle window in the right part and click "makeJar" on Android studio like this,
Then go to build/libs dir, you will see your jar file.
Hope that it is helpful for u.
Good Luck #.#
Luna