I have an android project where a library is included (aar). Gradle will unpack and store the files in the gradle cache (.gradle\caches\transforms-2). I need a gradle script where I can retrieve a file from this cache and move it into my project. Does anybody know how this can be done?
The moving part is working. I just need to get the correct path
tasks.register('moveFile', Copy) {
from "${path_to_build_cache}/path/to/folder/file.conf"
into "${project.rootDir.path}/path/to/folder/"
}
EDIT
I have now tried the solution posted by #tim_yates. The problem is that I am now receiving the error CustomMessageMissingMethodException: Could not find method from() for arguments [ZIP 'C:\Users\nthemmer\.gradle\caches\modules-2\files-2.1\path\to\aar on task ':my-project:movefiles' of type org.gradle.api.DefaultTask It seems that the aar file is read correctly but it has not only one file.
Instead of searching the cache, you should be able to use Gradle to find it for you...
Here's an example:
configurations {
aar
}
dependencies {
aar('com.mikhaellopez:circularimageview:4.3.0#aar')
}
tasks.register('moveFile', Copy) {
from(zipTree(configurations.aar.singleFile)) {
include "res/values/values.xml"
}
into project.layout.buildDirectory.dir('here')
}
That copies the file into ./build/here/res/values/values.xml
Edit
So there's probably multiple ways of doing this, but here's one.
Define a configuration that we will use for the single dependency you want a file from, and make compileClasspath extend from it (so the dependency ends up back in the compile classpath where it was previously)
configurations {
aar
compileClasspath.extendsFrom aar
}
Then in the dependencies where you reference the aar, you should be able to use aar instead of compileClasspath
dependencies {
aar('com.mikhaellopez:circularimageview:4.3.0#aar')
}
Then you can use the moveFile task from above, and there will just be a single file
Not 100% sure what you have currently, so not sure how this fits in, but it should give you a good direction.
Here's the full build file which runs on Gradle 7.2 and uses the circularimageview arr off maven central as the test subject
plugins {
id('java')
}
repositories {
mavenCentral()
}
configurations {
aar
compileClasspath.extendsFrom aar
}
dependencies {
aar('com.mikhaellopez:circularimageview:4.3.0#aar')
}
tasks.register('moveFile', Copy) {
from(zipTree(configurations.aar.singleFile)) {
include "res/values/values.xml"
}
into project.layout.buildDirectory.dir('here')
}
Related
Context
I'm trying to implement Dokka in a project using the it's fat-jar. To be able to generate documentation. I need the classpath of the dependencies that the project uses. Dokka accepts jars as classpath to be able to generate documentation. I using Groovy to generate a Gradle task to be able to extract the dependencies for each subproject
Problem
Since the project uses AAR dependencies, I need the classes.jar of those files.
What I came up so far
I'm able to retrieve the AAR directory in the .gradle cache directory, however that points to, as I said, the AAR. I don't want to unzip the file to be able to extract the classes.jar in it, since that will be very performance-heavy.
def classpaths = []
subprojects.each { project ->
classpaths.addAll(project.android.getBootClasspath().collect { it.path })
project.configurations.each { configuration ->
try {
classpaths.addAll(configuration.files.collect { it.path })
} catch (Exception ignored) {
}
}
}
This code will retrieve most of the AARs. But it doesn't seem to be printing the dependencies (e.g. Glide)
Question
How do I get the transformed directory of the dependencies or their classes.jar path for all the dependencies the project uses? I need to be able to get the path dynamically.
Example of the directory I need: /Users/user/.gradle/caches/transforms-1/files-1.1/glide-4.8.0.aar/efaa2fb5a51ab0ecf0ac00dd6a8d019b/jars/classes.jar
I am having trouble getting a jar library to show up under External Libraries in Android Studio. I am trying to add javadoc for this library, and the only method I've found online is to right click on the library in External Libraries and select Library Properties....
The project structure is a tree of many modules:
rootsdk /
main.jar
main-javadoc.jar
plugins /
plugin1 /
build.gradle
...
plugin2 /
build.gradle
...
...
The dependency is declared in the build.gradle files like:
compileOnly files('../../main.jar')
If I open up the individual directories plugin1, then the dependency shows up in External Libraries correctly. But if I open up the rootsdk project, it does not appear. All of the modules are listed and compilable from the root project, and I can use classes defined in the library just fine, but it does not appear under External Libraries, so I cannot add the javadoc for it.
The strange thing is some of the plugins use other libraries, but defined differently:
repositories {
flatDir {
dirs 'libs'
}
}
...
implementation(name: 'core-debug', ext: 'aar')
And these libraries show up under External Libraries as expected.
Is there something missing to force main.jar to show up under External Libraries, or is this a bug in AS?
It's a silly thing, but if you make it an Ivy or Maven repository, it should work. files don't. Both of the below solutions should support -sources and -javadoc suffixes. I think IDEA only implemented artifact resolution from repositories, and didn't think about direct file references.
Ivy
repositories {
def repoRoot = file(rootProject.projectDir)
ivy {
name = "local libs"
url = repoRoot.toURI()
patternLayout {
artifact("[module](-[classifier]).[ext]")
}
metadataSources {
artifact()
}
}
}
dependencies {
// `local` group and version `0` are just a hack so Gradle dependency notation can be used.
implementation("local:main:0")
implementation("local:core-debug:0#aar")
}
Maven
You can do something similar to above, but the repo structure is less flexible. You need to move the .jar/.aar files around. I recommend creating a folder for them (even if there's one right now). In the example I called it libs.
repositories {
def repoRoot = file(rootProject.projectDir.resolve("libs"))
exclusiveContent {
// Work around
// > Could not GET 'https://repo.gradle.org/gradle/libs-releases-local/local/main/0/main-0.pom'. Received status code 409 from server: Conflict
// by not allowing Gradle to contact other repositories for "local" files.
filter {
includeGroup("local")
}
forRepository {
maven {
name = "local libs"
url = repoRoot.toURI()
metadataSources {
artifact()
}
}
}
}
}
dependencies {
// `local` group and version `0` are just a hack so Gradle dependency notation can be used.
implementation("local:main:0")
implementation("local:core-debug:0#aar")
}
The error message will tell you where to put it, for example:
* What went wrong:
Execution failed for task ':...'.
> Could not resolve all files for configuration ':...'.
> Could not find local:main:0.
Searched in the following locations:
- file:/.../libs/local/main/0/main-0.jar
Required by:
project :...
> Could not find local:core-debug:0.
Searched in the following locations:
- file:/.../libs/local/core-debug/0/core-debug-0.aar
Required by:
project :...
Note that while this is more complex, it's also more flexible, because you can hand-write or download POM files and therefor include transitive dependencies for the local JAR files, just remove the metadataSources block if you have POM XML files for your artifacts.
metadataSources
This magic is worth a mention (docs):
metadataSources {
artifact()
}
it tells Gradle, that there's no metadata (POM or Ivy XML file) associated with the artifacts in the repository, that there's only artifacts exists. Without this, it would fail by looking for metadata.
I've came across following library
https://github.com/afollestad/material-dialogs
and i have tried to add the dependencies to my project but gradle consistently fails to sync saying that some .aapt file exploded or something
Can some one please guide me on how to add this library correctly and screenshots of how to do it would be great.
Have you add this in build.gradle(Project) (you need to paste this two times - there are two repositoies blocks).
repositories {
maven { url "https://jitpack.io" }
}
And this to other build.gradle(Module:app)
compile('com.github.afollestad.material-dialogs:core:0.8.5.1#aar') {
transitive = true
}
I had my own customized framework(android.jar) and want to use it within Android Studio. I had description in my build.gradle like:
dependencies {
compile files('myandroid.jar')
}
But Android Studio still use the default framework(android.jar). Expected situation is like Eclipse, I can arrange the order of libraries. In Android Studio, I can only arrange external libraries' order and have nothing to do with the default framework library. Is there a way to let my customized android.jar had higher order than the default one?
Thanks a lot!
Place this line inside your dependencies:
provided files('libs/myandroid.jar')
If still not work, so we can add our library to build classpath. In application's build.gradle, add these:
allprojects {
repositories {
jcenter()
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\mylibs.jar')
}
}
}
I placed mylib.jar is in app/libs. There maybe some errors display on IDE, but application's build will be OK.
What you can do is adding your .jar in your libs folder, then right clic on it and select add as a library.
Then if it doesnt work already, try to right clic on your project folder and select Open Modules settings. You can manage your dependency and your libraries there.
Try this ,In your modules's build.gradle file .
dependencies {
compile files('libs/myandroid.jar')
}
Try this:
allprojects {
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:/mylib.jar')
}
}
}
http://www.jianshu.com/p/a25a85b6372d
How to put my libraries in front of android.jar by editing build.gradle in Android-Studio
So I've been playing in Gradle and Android Studio now since the early days of their inception. However, I find myself banging my head on the walls far more times then it is worth at times :(.
I have spent a day and a half trying to resolve my current dilemma.
Where I work we use a lot of shared library projects. This means that unlike Gradle's native assumption, my projects are NOT all nested under one parent project. (BUT this is NOT my question) I have gotten this working.
After our projects have become complete and ready to go, it has been asked to create an SDK for the current project infrastructure for external use. Now in the old IntelliJ I would simply generate some JavaDocs and create an Artifact that includes all dependencies, then another on that does not include the dependency jars and name them respectfully.
However, in Gradle this appears to be very difficult, maybe even unsupported, and I can't find anyone else that has done it after more then 10 hours of Googling and trial and error, I finally decided to make a demo project to show exactly what I'm doing and what I'm trying to accomplish.
I need to do a few things.
Generate a Jar file that includes ALL module dependency code and dependent Jar files
Generate a Jar file that includes ALL module dependency code and ZERO dependent Jar files
Generate an AAR file that includes All module dependency code and dependent Jar files as well as resources for launching our Activity if they want to use it.
Generate an AAR file that includes All module dependency code and ZERO Jar files as well as resources for launching our Activity if they want to use it.
So there in lies my problem. Each module when running a Task with (type: Jar) simply generates it's own code. I'm managed to get the dependent Jar files to compile in once, but then there is no regular source code, but I have NEVER been able to get a Module's source code to be included in the Jar file which is my biggest hurdle right now.
Here is a list of Tasks that I have tried without accomplishing this simple task yet.
evaluationDependsOn(':dependencyModule')
task myJar(type: Jar){
appendix = 'myJar'
from android.sourceSets.main.allSource.files
}
task uberJar (type: Jar){
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
}
task fatJar(type: Jar, dependsOn: 'compileJava') {
from {
sourceSets.main.output.classesDir
}
// Add all dependencies except for android.jar to the fat jar
from {
configurations.compile.findAll {
it.getName() != 'android.jar'
}.collect {
it.isDirectory() ? it : zipTree(it)
}
}
archiveName = 'fatJar.jar'
}
task jarFat(type: Jar) {
appendix = "fat"
from android.sourceSets.main.java
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.allSource
classifier = 'sources'
}
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)
task jar(type: Jar) {
from android.sourceSets.main.allJava
}
task deployJar(type: Jar, dependsOn: jar) {
baseName = project.name + '-deploy'
deps = configurations.runtime + configurations.archives.allArtifactFiles
depClasses = { deps.collect { it.isDirectory() ? it : zipTree(it) } }
from(depClasses) {
exclude 'META-INF/MANIFEST.MF'
}
}
task modelJar(type: Jar) {
from sourceSets.main.output
}
task jarWithDependency(type: Jar){
from android.sourceSets.main.classesDir
from {configurations.compile.collect {zipTree(it)}}
}
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.allJava
}
Nothing has quite done the job yet. Any help would be greatly appreciated!!
Thanks in advance for taking the time to look at this.
I have the full functioning Sample Project if anyone would like it, but I don't see an option to upload here so is the link to the Demo project I built. It is very small and very easy to follow. One class or method basically per Project.
Demo Project
Using the application plugin, you can just call "distZip" to get a zip with all the libraries. By default you get a bin directory with a batch file and a shell script to run the program and a lib directory with all the jar files.
You probably want to update the Manifest to include all the necessary libraries like the following (I have additional stuff in mine).
EDIT I removed the references to "project" because it should not be necessary in this instance.
jar.doFirst
{
// aggregate all the jars needed at runtime into a local variable (array)
def manifestClasspath = configurations.runtime.collect { it.name }
// remove duplicate jar names, and join the array into a single string
manifestClasspath = manifestClasspath.unique().join(" ")
// set manifest attributes - mainClassName must be set before it is used here
manifest.attributes.put("Main-Class", mainClassName)
manifest.attributes.put("Class-Path", manifestClasspath)
}
I'm not an Android developer, so you would have to add some additional code for the AAR stuff.
Update from Author.
Ok as time has gone on, I have learned that the best practice is to allow dependency management tools to do their job and not try to package these files as such.
You can create fat jars and fat aar files, there are plugins to help, but it is hacky and doesn't allow the user to exclude transitives properly if they are nested in the compiled product. the exclude is intended for maven server pom files to include or exclude dependency files.
So using a Maven Repo Server is the best way to manage this instead as the FAT compiler plugins are unreliable and break with each gradle update and more importantly limit your user's ability to exclude "some and not all" when it comes to transitives.
So stay away from doing this if you can avoid it and do it the right way I recommend it. I'll leave this post up in case anyone else was heading down this bad path as well and hope you move to the right path of dependency management servers with transitive dependency managed by pom files.