Which dependency will Gradle choose given multiple maven repository? - android

In Gradle project, we can define multiple remote / local Maven repository.
buildscript {
repositories {
mavenLocal()
mavenCentral()
jCenter()
maven {
url 'https://example1.mavenrepo.com/public'
}
maven {
url "https://example2.mavenrepo.com/release"
}
}
dependencies {
classpath 'com.example.mydependencies:mylibrary:1.0.0'
}
}
If mylibrary exist in all of Maven repo. Which one will Gradle choose? Can I configure Gradle to only download mylibrary in certain Maven repo?

As you can find in the doc
A project can have multiple repositories. Gradle will look for a dependency in each repository in the order they are specified, stopping at the first repository that contains the requested module.

I don't think there is a way to point to the gradlew to use particular repository or order it. Gradlew by design uses a single repository for all dependencies. If any of them fail, the build fails.
[Refer]: https://github.com/gradle/gradle/issues/7965

Related

Gradle build: Server returned HTTP response code: 401 for URL https using artifactory

In the build.gradle of a module, I'm trying to execute the following line
if (!jsonFile.exists()) {
new URL(mapUrl).withInputStream{ i -> jsonFile.withOutputStream{ it << i }}
}
The build fails with the error:
Server returned HTTP response code: 401 for URL: https://artifactory.myurl.com/artifactory/myfile.json
I pass the credentials to my gradle script as follows:
buildscript {
repositories {
google()
jcenter()
maven {
url 'https://artifactory.myurl.com/artifactory/'
credentials {
username = "myuser"
password = "mypwd"
}
}
}
}
Well, there are several problems in your code:
First, withInputStream and withOutputStream are Groovy JDK enhancements on the Java classes URL and File. This is not related to any Gradle functionality and only works, because Gradle is built on top of Groovy. As far as I know, it is not possible to pass credentials to withInputStream, so it only works for resources that are publicly available.
Regarding the second part of your code snippet, lets first take a look at the buildscript block. It is a special Gradle block that always will be evaluated first (and must be at the top of a build.gradle file). The reason for this is that this block basically provides as a setup for your build script (aka the build.gradle file). Usually this block defines the repositories and the dependencies that need to be resolved for the build script to work (e.g. plugins). Regular project dependencies and their repositories may be defined outside of the buildscript block. They are resolved when other task (e.g. compilation tasks) need them.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'example-plugins:my-fancy-plugin:0.0.1'
}
}
// the build script stops here to resolve my-fancy-plugin from jcenter
repositories {
jcenter()
}
dependencies {
implementation 'example-libraries:my-cool-library:0.0.1'
}
// this won't be resolved directly, only if a task that needs *implementation* dependencies is run
The repositories/dependencies mechanism is mainly used to resolve *.jar files that serve as dependencies of JVM-based projects. The repositories are usually Maven repositories. Maven repositories follow a specific layout, so the dependency descriptors (e.g. example-libraries:my-cool-library:0.0.1) will be mapped to URLs (e.g. example/libraries/my-cool-library/0.0.1/my-cool-library-0.0.1.jar). Gradle then tries to download the dependencies from this URL. Since your path does not follow the Maven repository layout, you can't download your file from a Maven repository.
For your use case you probably should not use the Gradle dependency resolution at all. There is a plugin that allows downloading files using a Gradle task (with support for authentication):
task downloadFile(type: Download) {
src 'https://artifactory.myurl.com/artifactory/myfile.json'
username = "myuser"
password = "mypwd"
dest buildDir
}
Alternatively you may define an Ivy repository with a custom repository layout.

Gradle look into wrong maven repository

when I sync my Android project, I keep seeing the following messages:
Gradle: Download https://s3.amazonaws.com/moat-sdk-builds/com/google/android/gms/play-services-ads-base/maven-metadata.xml
Gradle: Download https://s3.amazonaws.com/moat-sdk-builds/com/google/android/gms/play-services-measurement-base/maven-metadata.xml
Gradle: Download https://s3.amazonaws.com/moat-sdk-builds/com/google/firebase/firebase-iid/maven-metadata.xml
These libraries should be found in google() repo, which is the first one in my settings:
allprojects {
repositories {
google()
jcenter()
// ...
maven { url "https://s3.amazonaws.com/moat-sdk-builds" }
}
}
However, it looks into maven { url "https://s3.amazonaws.com/moat-sdk-builds" } and wastes a lot of time. What's going on here? And is there any way to debug it? Thanks.
You can try to customize dependency resolution behaviour or declare repository filters.
Declaring a repository filter is as easy as this:
allprojects {
repositories {
google()
jcenter()
// ...
maven {
url "https://s3.amazonaws.com/moat-sdk-builds"
content {
// Does only include this group
includeGroup "moat.sdk"
}
}
}
}
There is also the option to exclude groups and enhance for example the build performance.
Take care that "Matching repositories to dependencies is an incubating feature." The API documentation provide more information about filter options.
You can find more information on the specific behaviour you experience below. When it comes to dependency resolution Gradle does inspect repositories in order.
How dependency resolution works
[...]
Given a required dependency, Gradle attempts to resolve the dependency by searching for the module the dependency points at. Each repository is inspected in order. Depending on the type of repository, Gradle looks for metadata files describing the module (.module, .pom or ivy.xml file) or directly for artifact files.
[...]
But as i understand it gradle 'visits' each repository irrespective of whether it has already found the 'correct' artifacts or not.
Once each repository has been inspected for the module, Gradle will choose the 'best' one to use. This is done using the following criteria:
For a dynamic version, a 'higher' concrete version is preferred over a 'lower' version.
Modules declared by a module metadata file (.module, .pom or ivy.xml file) are preferred over modules that have an artifact file only.
Modules from earlier repositories are preferred over modules in later repositories.
When the dependency is declared by a concrete version and a module metadata file is found in a repository, there is no need to continue searching later repositories and the remainder of the process is short-circuited.
[...]
Introduction to Dependency Management - How dependency resolution works

getting failed to resolve when adding dependency

I am trying to add an external dependency from jcenter
compile 'com.droidninja:filepicker:2.0.4'
but I keep getting these errors and I can't figure out what is going wrong.
I have seen the same errors come up in lot of projects but nobody seems to know whats going wrong.
The problem is not with the dependency you just added but the Android Support library's dependencies. The latest SDK updates move towards using the remote Google Maven repository instead of downloading everything to be available locally. In order to fix dependency resolution problems follow the Adding Support Libraries guide. Really briefly this is what you have to do:
Open your project's build.gradle (note that this is not the module's file!)
Add the Google Maven repo to the project repositories:
allprojects {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
}
It's also recommended to add the repo to the buildscript block too, so later on the Gradle plugins can be downloaded from there too:
buildscript {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}

Creating cordova 5.x android gradle build offline

Recently I upgraded my Cordova project from Cordova 3.0 to 5.3.3 and Android platform from 3.6 to 4.1. New android platform uses gradle for build and need to connect to internet (maven repo) every day for building. Once it connects to repo, it does not require connection for that day.
I am working behind the proxy which does not have access to maven repo. I am new to gradle build and want to configure gradle for offline building cordova application.
Here are environment details
OS -> MAC OSX
Cordova version -> 5.3.3
Cordova Android platform version -> 4.1
Kindly suggest.
Dependencies are declared in Gradle in the dependencies section and the repositories section controls where the dependencies are fetched from. For example:
repositories {
jcenter()
}
dependencies {
compile 'com.google.guava:guava:18.0'
}
This says, guava:18.0 is fetched during compile time, from the jcenter() repository. You can also use maven central as:
repositories {
mavenCentral()
}
A custom repo like a company repo as:
repositories {
maven {
url "http://repo.mycompany.com/maven2"
}
}
or, the local .m2 repo as:
repositories {
mavenLocal()
}
You can define multiple repositories as well:
repositories {
mavenLocal()
jcenter()
}
Gradle searches for dependencies in the order that the repositories are listed. So it will look in local .m2 first, and if a matching dependency isn't available, it goes out to JCenter to download dependencies.

Structure of build.gradle

In the following simple build.gradle file, i have some basic questions.
1.In repositories, when i specify mavenCentral(), is it the repository where all the libraries that i specify like compile 'com.android.support:support-v4:21.0.2'will be searched? Is there anything else for this apart from mavenCentral()? And what is the url required for after that(oss.sonatype..)?
2.What are the items that should be specified in classpath? Why cant the classpath items be specified like we specify the support libraries?
3.And for using a third party library, i had to specify an Amazon AWS URL at the bottom in allProjects() section. Why is this URL required?
buildscript {
repositories {
mavenCentral()
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
classpath 'com.jimdo.gradle:gradle-apt-plugin:0.2-SNAPSHOT'
}
}
allprojects {
repositories {
mavenCentral()
maven {
url "https://s3-ap-southeast-1.amazonaws.com/abc-release/abc/"
}
}
}
1.In repositories, when i specify mavenCentral(), is it the repository where all the libraries
No, you also have an implicit local Maven repository (usually at ~/.m2) which can also be searched for locally installed packages. The newer Android Studio builds use jcentral rather than Maven central, but the concept is the same: a central repository for packages.
2.What are the items that should be specified in classpath? Why cant the classpath items be specified like we specify the support libraries?
These are build tool (i.e. gradle) dependencies. Your app's dependencies are outlined in the app module's specific build.gradle file.
3.And for using a third party library, i had to specify an Amazon AWS URL at the bottom in allProjects() section. Why is this URL required?
Because their libraries are not in Maven central. So you're effectively pointing Maven to an outside repository you wish to use for your app and any of its libraries.
1.In repositories, when i specify mavenCentral(), is it the repository where all the libraries that i specify like compile 'com.android.support:support-v4:21.0.2'will be searched?
Yes, but only if it isn't in buildscript block.
Everything inside buildscript is used by build system – gradle and possibly some libraries for it.
allprojects.repositories is place where you declare repositories where libraries used by your application will be searched.

Categories

Resources