Module library Jar not shown in External Libraries in Android Studio - android

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.

Related

Find cached files of unpacked aar files in gradle script

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')
}

How to access extra properties from project build.gradle in modules

So I'm trying to setup Maven Publish in my library which has several modules in it.
I am following this tutorial since the whole process is imo not that well documented on the Android Documentation. However, I am stuck at the point Customizing POM File Generation — Basics. I added the external info in my project build.gradle and try to add the publishing information in the modules build.gradle. When I try to sync Gradle I get the following error:
A problem occurred configuring project ':projectname'.
> Failed to notify project evaluation listener.
> Cannot get property 'pomGroupID' on extra properties extension as it does not exist
> Cannot get property 'pomGroupID' on extra properties extension as it does not exist
The code in my build.gradle files looks like this:
Project:
buildscript {
// POM information for publishing the library
ext {
pomVersion = '4.23'
pomGroupID = "com.randomname.stackoverflowquestion"
}
....
Module:
project.afterEvaluate {
publishing {
publications {
maven(MavenPublication) {
groupId project.ext.pomGroupID
artifactId project.name
version project.ext.pomVersion
artifact(bundleReleaseAar)
}
}
}
}
Any idea on what could be the problem in my case?
The problem was very simple. Only had to change
project.ext.pomVersion
to
project.pomVersion

How to version local gradle dependencies?

My Android project contains a library that is shipped as AAR file.
There are multiple options to include local AAR files.
I can declare a file dependency:
implementation files('libs/mylib.aar')
Or I can put the AAR into another module and then use a project dependency:
implementation project(':mylibmodule')
However, I want to specify the exact version of my library:
mylib:1.0.0
Unfortunately, I do not know how to specify the version without using some remote repository.
Note that I do not want to upload the library to JitPack, MavenCentral or similar.
All I want is to specify the version of a local AAR file.
Update
The AAR file is a Zip-File with the following content:
/proguard.txt
/R.txt
/AndroidManifest.xml
/public.txt
/classes.jar
/res/values/values.xml
Note that the AndroidManifest.xml contains the version of the library.
However, I assume that gradle always expects a pom file for the versioning information.
I realized that gradle allows to specify a local Maven repository at a specific path:
repositories {
maven {
url uri("${projectDir}/mylibdir")
}
}
To use a local Maven repository, I need to build my library as a Maven artifact. To create a Maven artifact, it suffices to create a POM file in the right subfolder.
The AAR file remains unchanged since Maven does not care about the artifact format.
Creating a Maven artifact can be automated with the maven-publish plugin, e.g.:
apply plugin: 'maven-publish'
publishing {
publications {
myRelease(MavenPublication) {
groupId 'com.foo'
artifactId 'my-artifact'
version '1.0.0'
artifact("$buildDir/outputs/aar/my-artifact.aar")
}
}
repositories {
maven {
url "$buildDir/repo"
}
}
}
However, since I do not really need to use Maven, the simpler choice is to add the version to the AAR file name.
I did this with the following snippet in the build.gradle of my library:
android.libraryVariants.all { variant ->
variant.outputs.all {
outputFileName = "${archivesBaseName}-${variant.name}-${defaultConfig.versionName}.aar"
}
}

Import library module that has dependency on local aar file

I have an Android Instant App with following structure:
B: base module
Installed: installed app module
Instant: instant app module
F: feature with functional specific to Installed app. F depends on local aar library local-lib located in project\F\libs.
F's build.gradle is following:
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
api ":local-lib#aar"
}
I tried to include F module to Installed app module like this:
dependencies {
implementation project(':B')
implementation project(':F')
}
But gradle couldn't resolve local-lib, giving error:
Error:Could not resolve all dependencies for configuration ':Installed:releaseCompileClasspath'.
> Could not find :local-lib:.
Searched in the following locations:
... some remote repositories ...
Required by:
project :Installed > project :F
I tried to duplicate libs folder to project\Installed\libs, and it worked. So basically I need 2 copies of local-lib to make this work? How should I organise imports to avoid duplication? Perfect case would be if libs folder was inside F module.
IMHO, the cleanest way to make it work would be to use some local repository, like a Maven, publish your local-lib here, and reference it from here, and do the same for each of your libraries. When you publish to an artifact repository manager - let's say a Maven - you will have your .aar coupled with a pom file, containing all the needed dependencies.
You have to keep in mind here that your aar is kind of a flat file, meaning, while you reference it somewhere, there is not way to keep track of the transitive dependencies of it (that's the job of the pom files on Maven).
This means that when you reference F in Installed, the F aar is added, but Installed doesn't know that it has to get local-lib in order for F to work properly, or doesn't know where. That's why you have lines on the remote repositories: gradle searches everywhere (in every possible place = in every repository you have listed) for the dependency.
When you copy/paste the code as a module of your project, the gradle knows what are the transitive dependencies because it can access the gradle file for each dependency.
When you copy the aar directly inthe Installed/libs folder, it also works because gradle checks here (you probably have a compile line in your gradle checking for that folder).
If you want to keep the flat file, you should try putting somewhere reachable by all modules, on the same folder level (take a look at that question), or you could try to add the local-lib as an Android module project, and not just put it in the libs folder.

Does anyone know how to resolve an ivy dependency in Android Studio?

Here is the repository:
https://asset.opendof.org/
I am trying to add the jar dependency found here:
https://asset.opendof.org/artifact/org.opendof.core-java/dof-oal/7.0.4/jars/
You will need to configure the repository and layout. Some repositories (like this one) are unique in that they separate artifacts (JARs, ZIPs, etc) from Ivy metadata. You'll have to tell Gradle what the layout (directory structure) of the repository looks like so it knows how to construct the download URLs. For more info see the Gradle documentation on Ivy repositories.
For your specific example you'll want to add the following to your build script:
repositories {
ivy {
url 'https://asset.opendof.org'
layout 'pattern' , {
artifact 'artifact/[organisation]/[module]/[revision]/[type]s/[artifact](.[ext])'
ivy 'ivy2/[organisation]/[module]/[revision]/ivy.xml'
}
}
}
dependencies {
compile 'org.opendof.core-java:dof-oal:7.0.4'
}

Categories

Resources