I have a library module where I used a dependency which is based on a private maven repository, I can use this dependency in my library and everything works well.
The problem occurs when I try to use the library module inside my application, the build is failing, for some reason is looking to get this dependency from a different maven repository (in this case, my personal one, which is available only in my app)
I've switched from implementation to api and viceversa, just so check if this might solve the issue, but it is not.
If I add the maven repository url also in my app, everything works well, but I don't what that. Is this the expected behaviour?
Thanks!
Yes, repositories declared in one subproject are not shared with other subprojects. Other than with Maven, repositories are also not taken from a dependency POM file or otherwise inherited from a dependency. On this topic, the Gradle docs state the following:
Strict limitation to declared repositories
Maven POM metadata can reference additional repositories. These will be ignored by Gradle, which will only use the repositories declared in the build itself.
However, you can probably centralize the repository declaration in your top-level settings.gradle(.kts) file:
dependencyResolutionManagement {
repositories {
// TODO Configure the shared repository here.
}
}
You can find more details on this centralization in the Gradle docs.
Related
I am working on a library that uses custom repositories (i.e. with specific URLs) to get some of the dependencies.
maven {
url 'https://someURL/'
}
I've published the library and set it on our private repository and noticed that I couldn't compile because gradle couldn't locate these dependencies. I could fix that by adding the same custom repositories to the testing app project-level build.gradle, but I want to know if there's an option to avoid this, meaning, have the testing application get the custom repositories information from the published packages.
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
I want to add AdView to my activity and I click on download and then it automatically implements the necessary library. But then I get the following error:
Error 1
I get the same error when I try to add GridLayout to my library.
Here is my gradle file: gradle file
I already tried to set the Global Gradle settings to offline work but it doesn't help.
I have android studio 3.4.2
This is a problem that bothers me for a while now and there seems no solution to this. Is it possible that these things are not available for androidx yet? Thank you for your help!
From the documentation:
To make the Google Play services APIs available to your app:
Open the build.gradle file inside your application module directory.
Note: Android Studio projects contain a top-level build.gradle file and a build.gradle file for each module. Be sure to edit the file for your application module. See Building Your Project with Gradle for more information about Gradle.
Add a new build rule under dependencies for the latest version of play-services, using one of the APIs listed below.
Ensure that your top-level build.gradle contains a reference to the google() repo or to maven { url "https://maven.google.com" }.
Save the changes, and click Sync Project with Gradle Files in the toolbar.
You can now begin developing features with the Google Play services APIs.
This is often a common mistake. If you have multiple repositories in your gradle, make sure that maven google is at the top of the list.
eg.
repositories {
maven { url "https://maven.google.com" }
...
}
This package:
// https://mvnrepository.com/artifact/com.google.android.gms/play-services-ads
implementation "com.google.android.gms:play-services-ads:18.1.1"
is either available from repository google() or from repository mavenCentral():
repositories {
google()
mavenCentral()
...
}
see the quick-start.
I already saw this question, but it is not helping me. First of all, I tried to add google play services in my project using:
dependencies{
compile 'com.google.android.gms:play-services:6.5.87'
}
It was showing me error:
Then I updated my studio to 1.0.1 and gradle to 1.0.0. And then I again synced the project with gradle. And it worked! It showed me another option despite of two options shown in above screenshot. It was "Install the library"(something like that). I clicked it and it popped up a dialog, and I installed the library(it was like downloadind using SDK manager and not like gradle downloads).
Now, I tried to download this library using:
compile('com.fortysevendeg.swipelistview:swipelistview:1.0-SNAPSHOT#aar') {
transitive = true
}
And it gives me error:
My android repository is updated:
Also, my internet connection is working fine. I tried to sync project many times, but same error all the time. I am not running gradle in offline mode:
How to fix this? And what is the permanent solution? And why is all this happening?
I found this question: Studio failed to download library from gradle repository which describes the exact same error, and that question had this bit of build script that you need to add to the build file that has the dependency statement in question:
repositories {
maven { url 'http://clinker.47deg.com/nexus/content/groups/public' }
}
When I do this, it works for me.
As to the general question of why this happens (and the better question of why the solution is different for different libraries):
Gradle, the build system that Android Studio uses, has the ability to automatically download library dependencies from the Internet. By and large this is a big boon for developers, because instead of having to manually download archive files, put them in the right place in your project, check them into source control, and repeat the process for new versions, now you just have to add a line of build script and the build system takes care of the housekeeping for you. The major downsides are Internet connectivity woes, which affect different developers to different degrees, and some added confusion about what it means when you get an error.
How does Gradle know where to download dependencies? Most Gradle build scripts contain a block that looks like this:
repositories {
jcenter()
}
or it may be mavenCentral() instead of jcenter(). This tells the build system to look in the JCenter or Maven Central global repositories (and JCenter is in a simplistic way of thinking about it a value-added mirror of MavenCentral); these contain archives of many versions of many, many, many libraries and are very convenient to use.
You can specify other repositories as well. This swipelistview library hasn't been uploaded to Maven Central, so the developer has made a repository for it available via a URL: if you add that URL to your repositories block, it will look for it there.
I was worried about the fact that you're accessing a SNAPSHOT version of the library -- these are supposed to be unpublished by definition. But adding a dependency on the snapshot version of the library in my test project worked for me, and looking around that URL in a web browser reveals that there's only a "1.0-" (trailing dash included) version of the library, so there's some subtletly there I'm missing; if you know more, please edit my answer or comment.
In any event, there are a couple caveats to this explanation. Some libraries aren't on Maven Central or on any Internet-accessible archive (at least they're not officially published by Android), but are instead published as part of the Android SDK download and maintained via the SDK manager. The Android support libraries and Google libraries fall under this category. If you get errors about those not being found, you have to fix it via the SDK manager.
How does the build system know to look in the SDK for those, since you didn't tell it via the repositories block? This behavior is hardcoded into the Android Gradle plugin.
The other caveat is that there's a detail that trips up a lot of people, which is that you actually have two repositories blocks, though with the usual Android Studio setup they're often in different files. One is in a buildscript block, which usually lives in the top-level build.gradle file and looks like this:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
The other often also lives in the top-level build.gradle, but you can augment it with another block in your module's build.gradle file. The top-level one looks like this:
allprojects {
repositories {
jcenter()
}
}
and a module-level one would look like one of the previous examples in this answer. What do all of these mean?
The buildscript block tells Gradle where to find build system plugins. These are plugins that enhance the functionality of the build system itself but don't say anything about your actual project. In Android projects, the Android Gradle plugin is in this category, and unlike the Android/Google libraries, this one does live on Maven Central. The repositories block (in coordination with the dependencies block, which is not the same as the dependencies block for your project, keep reading) in buildscript tells the build system where to go look for these plugins.
The allprojects block in the top-level build file tells the build system to apply the bit of contained script to all build files in the project. In this example, it's telling it to add a repositories block pointing to JCenter to all subprojects. This is a convenience so you don't have to copy/paste it into multiple build files in your modules.
In your modules, you also have a repositories block, which in conjunction with the allprojects thingy, tells the build system where to go to get library dependencies for your project, as was previously discussed.
Say I need to use some proprietary jars in my android library. I want my library to be conveniently available from Maven Central, but I can't just put dependencies there due to legal issues.
I figured it's possible to use Internal Repository to host dependencies so they would be resolved automatically.
I've used Github repo, just like this one, and declared it in library pom.xml
However Gradle doesn't seem to be resolving this dependencies. If I manually declare my repository in main build.gradle everything works fine. Am I doing something wrong here, or android gradle plugind just don't support internal repositories?
It's discouraged in the Maven community to have repository declarations in published POMs, and Gradle won't honor them. Instead, downstream builds will have to declare the internal repository in one way or another (which shouldn't be a big deal).
If you (only) publish POMs for proprietary dependencies to Maven Central (which is a common solution to this problem at least if you own the dependencies), downstream builds will need to declare the internal repository as follows:
repositories {
maven {
url "https://repo1.maven.org/maven2"
artifactUrls "https://some.internal.repo"
}
}
If you don't publish proprietary dependencies to Maven Central at all (not even POMs), downstream builds will have to declare the internal repository as another regular Maven repository:
repositories {
mavenCentral()
maven {
url "https://some.internal.repo"
}
}
Note however that last time I checked, one of the rules of publishing to Maven Central was that dependencies needed to be available from Maven Central as well.
PS: Whether you are publishing a Java or Android library shouldn't matter here.