Gradle changed it's behavior when I updated from 5.0 to 5.1.
Lets assume that we have an android project with single module named library.
On Gradle 5.0 (and previous versions) when I executed ./gradlew assembleRelease or ./gradlew assembleDebug generated output was library-release.aar or library-debug.aar respectively.
After I updated to Gradle 5.1 (I also tried 5.1.1) it generates only library.aar for any build type without any build-type classifier in output file name.
So my question is: how can I force Gradle 5.1 to set correct output file naming for different build types like it was before? Below is my library module's build.gradle.kts, but I doesn't think that there is something wrong with it:
import org.jetbrains.kotlin.config.KotlinCompilerVersion
plugins {
id("com.android.library")
id("kotlin-android")
id("maven-publish")
}
val libraryVersion = "1.5.0"
android {
compileSdkVersion(28)
defaultConfig {
minSdkVersion(16)
targetSdkVersion(28)
versionCode = 1
versionName = libraryVersion
}
lintOptions {
isAbortOnError = false
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}
}
dependencies {
implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
implementation(kotlin("stdlib-jdk7", KotlinCompilerVersion.VERSION))
}
UPDATE:
If I add a following code to build.gradle.kts:
afterEvaluate {
android.libraryVariants.forEach { libraryVariant ->
libraryVariant.outputs.forEach { output ->
println(output.outputFile.name)
}
}
}
It will print:
library-debug.aar
library-release.aar
Now it starts looking like a bug in gradle 5.1
So as we can see in https://github.com/gradle/gradle/issues/8328, it is a bug which is fixed in Android Gradle Plugin 3.4.
libraryVariants.all { variant ->
variant.outputs.all { output ->
def filePrefix = "$buildDir/outputs/aar/$archivesBaseName"
outputFileName = "${archivesBaseName}-${version}.aar"
def fileSuffix = "aar"
def originalFile = file("$filePrefix-${variant.buildType.name}.$fileSuffix")
def renamedFile = "$filePrefix-${variant.buildType.name}-$version.$fileSuffix"
tasks.named("assemble").configure {
doLast {
originalFile.renameTo(renamedFile)
}
}
}
}
where archivesBaseName and version can defined in default block of libraries build.gradle
Related
I am trying to extract and use the architecture of the artifact to compose the output file name:
void defineDefaultVariantsAPK(String appName) {
defineVariantsAPK({ variant, output ->
def versionName = variant.versionName
def versionCode = "-(${variant.versionCode}"
def buildLetter = variant.buildType.name == "release" ? "-R" : "-D"
def flavor = variant.productFlavors.size() > 0 ? "-${variant.productFlavors[0].name}" : ""
def architecture = "-" + output.getFilter(com.android.build.OutputFile.ABI)
"v${versionName}${versionCode}${buildLetter}${flavor}${architecture}--${appName}.apk"
})
}
void defineVariantsAPK(Closure nameBuild) {
android {
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File((String) output.outputFile.parent, nameBuild(variant, output))
}
}
}
}
for some reason many posts says that that is the solution, but my gradle fails on:
> Could not get unknown property 'com' for project ':app' of type org.gradle.api.Project.
I've tried to use import:
unable to resolve class com.android.build.OutputFile
configuration:
com.android.tools.build:gradle:2.3.3
Gradle version 3.5
So I really wonder, what am I doing different that it doesn't work?
Beggining with Gradle 3.0.0 you can do it like this:
applicationVariants.all { variant ->
variant.outputs.all { output ->
def appName = "AppName_"
def buildType = variant.variantData.variantConfiguration.buildType.name
def architecture = output.getFilter(com.android.build.OutputFile.ABI)
def newName
if (buildType == 'debug') {
newName = "${appName}debug_${defaultConfig.versionName}_${architecture}.apk"
} else {
newName = "${appName}release_${defaultConfig.versionName}_${architecture}.apk"
}
outputFileName = newName
}
}
*put this in your module(app) build.gradle file.
This code works for me with gradle 3+ for android
android.applicationVariants.all { variant ->
variant.outputs.all { output ->
def architecture = output.filters[0].identifier
outputFileName = "myapp-${architecture}-${variant.versionName}.apk"
}
}
Where did you define this function? Try to move it you your app/build.gradle file as that is where buildscript is and gradle loads classes from it into classpath.
So following #blazsolar suggestion I've moved the method to the app build gradle file, the move itself was not the solution, when I tried to add the import:
import com.android.build.OutputFile
for some reason the IDE (Android studio) has decided to delete the import..
but once I've this import:
import com.android.build.OutputFile.FilterType
it was just fine!
but that is not the end of it... I want the method to be in a common gradle file, that all my project can reuse.
once I've added the last import to the common gradle file... the import figging disappeared again..
I am left with yet another question
update:
So I've update Android plugin and gradle version to 3.0.1 and 4.1 respectively, and now... things have change.. now there is no
com.android.build.OutputFile.FilterType
Now you need to use:
com.android.build.VariantOutput.ABI
Just in case anyone wonder...
I've juste added some flavors (or productFlavors if you want) to my project.
The fact is that when I publish the library to bintray, all flavors are uploaded (which is great), but I'm unable to use them. The plugin used is the official one here.
The uploaded aar:
androidsdk-0.0.4-fullRelease.aar
androidsdk-0.0.4-fullDebug.aar
androidsdk-0.0.4-lightRelease.aar
androidsdk-0.0.4-lightDebug.aar
As you noted, the fullRelease is named as the classifier, see doc chapter 23.4.1.3.
I am searching for a solution to choose which flavors that I want to upload.
I've already looked at bintray examples (here and here) and this, with also other examples but I'm still stuck.
Here is my current script:
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
buildscript {
repositories {
jcenter()
}
}
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 9
targetSdkVersion 23
versionCode 64
versionName "0.0.4"
}
publishNonDefault true
productFlavors {
full {
}
light {
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
fullCompile 'com.squareup.picasso:picasso:2.5.0'
}
version = android.defaultConfig.versionName
uploadArchives {
repositories.mavenDeployer {
pom.project {
packaging 'aar'
}
}
}
////////////////////////////////
// Bintray Upload configuration
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")
configurations = ['archives']
pkg {
repo = "MyRepo" // repo name
userOrg = 'hugo'
name = "AndroidSDK" // Package name
websiteUrl = siteUrl
vcsUrl = gitUrl
publish = true
}
}
To import the library I'm currently using this:
compile ('com.example.lib:sdk:0.0.8:fullRelease#aar') {
transitive = true;
}
I faced the same challenge, and here's the best I could make yet:
Using mavenPublications and the gradle maven-publish plugin along the bintray plugin, you can publish any variant to mavenLocal and bintray.
Here's the publish.gradle file I apply at the end of all my project's library modules I want to publish:
def pomConfig = {
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id 'louiscad'
name 'Louis CAD'
email 'louis.cognault#gmail.com'
}
}
scm {
connection 'https://github.com/LouisCAD/Splitties.git'
developerConnection 'https://github.com/LouisCAD/Splitties.git'
url siteUrl
}
}
def publicationNames = []
publishing.publications {
android.libraryVariants.all { variant ->
if (variant.buildType.name == "debug") return // Prevents publishing debug library
def flavored = !variant.flavorName.isEmpty()
/**
* Translates "_" in flavor names to "-" for artifactIds, because "-" in flavor name is an
* illegal character, but is well used in artifactId names.
*/
def variantArtifactId = flavored ? variant.flavorName.replace('_', '-') : project.name
/**
* If the javadoc destinationDir wasn't changed per flavor, the libraryVariants would
* overwrite the javaDoc as all variants would write in the same directory
* before the last javadoc jar would have been built, which would cause the last javadoc
* jar to include classes from other flavors that it doesn't include.
*
* Yes, tricky.
*
* Note that "${buildDir}/docs/javadoc" is the default javadoc destinationDir.
*/
def javaDocDestDir = file("${buildDir}/docs/javadoc ${flavored ? variantArtifactId : ""}")
/**
* Includes
*/
def sourceDirs = variant.sourceSets.collect {
it.javaDirectories // Also includes kotlin sources if any.
}
def javadoc = task("${variant.name}Javadoc", type: Javadoc) {
description "Generates Javadoc for ${variant.name}."
source = variant.javaCompile.source // Yes, javaCompile is deprecated,
// but I didn't find any working alternative. Please, tweet #Louis_CAD if you find one.
destinationDir = javaDocDestDir
classpath += files(android.getBootClasspath().join(File.pathSeparator))
classpath += files(configurations.compile)
options.links("http://docs.oracle.com/javase/7/docs/api/");
options.links("http://d.android.com/reference/");
exclude '**/BuildConfig.java'
exclude '**/R.java'
failOnError false
}
def javadocJar = task("${variant.name}JavadocJar", type: Jar, dependsOn: javadoc) {
description "Puts Javadoc for ${variant.name} in a jar."
classifier = 'javadoc'
from javadoc.destinationDir
}
def sourcesJar = task("${variant.name}SourcesJar", type: Jar) {
description "Puts sources for ${variant.name} in a jar."
from sourceDirs
classifier = 'sources'
}
def publicationName = "splitties${variant.name.capitalize()}Library"
publicationNames.add(publicationName)
"$publicationName"(MavenPublication) {
artifactId variantArtifactId
group groupId
version libraryVersion
artifact variant.outputs[0].packageLibrary // This is the aar library
artifact sourcesJar
artifact javadocJar
pom {
packaging 'aar'
withXml {
def root = asNode()
root.appendNode("name", 'Splitties')
root.appendNode("url", siteUrl)
root.children().last() + pomConfig
def depsNode = root["dependencies"][0] ?: root.appendNode("dependencies")
def addDep = {
if (it.group == null) return // Avoid empty dependency nodes
def dependencyNode = depsNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
if (it.hasProperty('optional') && it.optional) {
dependencyNode.appendNode('optional', 'true')
}
}
// Add deps that everyone has
configurations.compile.allDependencies.each addDep
// Add flavor specific deps
if (flavored) {
configurations["${variant.flavorName}Compile"].allDependencies.each addDep
}
// NOTE: This library doesn't use builtTypes specific dependencies, so no need to add them.
}
}
}
}
}
group = groupId
version = libraryVersion
afterEvaluate {
bintray {
user = bintray_user
key = bintray_api_key
publications = publicationNames
override = true
pkg {
repo = 'splitties'
name = project.name
desc = libraryDesc
websiteUrl = siteUrl
issueTrackerUrl = 'https://github.com/LouisCAD/Splitties/issues'
vcsUrl = gitUrl
licenses = ['Apache-2.0']
labels = ['aar', 'android']
publicDownloadNumbers = true
githubRepo = 'LouisCAD/Splitties'
}
}
}
In order for this to work, I need to have the bintray_user and bintray_api_key properties defined. I personally just have them in my ~/.gradle/gradle.properties file like this:
bintray_user=my_bintray_user_name
bintray_api_key=my_private_bintray_api_key
I also need to define the following ext properties I used in the publish.gradle file in my root project's build.gradle file:
allprojects {
...
ext {
...
// Libraries
groupId = "xyz.louiscad.splitties"
libraryVersion = "1.2.1"
siteUrl = 'https://github.com/LouisCAD/Splitties'
gitUrl = 'https://github.com/LouisCAD/Splitties.git'
}
}
And now, I can finally use it in my android library module, where I have multiple productFlavors. Here's a snippet from a publishable library module's build.gradle file:
plugins {
id "com.jfrog.bintray" version "1.7.3" // Enables publishing to bintray
id "com.github.dcendents.android-maven" version "1.5" // Allows aar in mavenPublications
}
apply plugin: 'com.android.library'
apply plugin: 'maven-publish' // Used for mavenPublications
android {
...
defaultPublishConfig "myLibraryDebug" // Allows using this library in another
// module in this project without publishing to mavenLocal or Bintray.
// Useful for debug purposes, or for your library's sample app.
defaultConfig {
...
versionName libraryVersion
...
}
...
productFlavors {
myLibrary
myLibrary_logged // Here, the "_" will be replaced "-" in artifactId when publishing.
myOtherLibraryFlavor
}
...
}
dependencies {
...
// Timber, a log utility.
myLibrary_loggedCompile "com.jakewharton.timber:timber:${timberVersion}"; // Just an example
}
...
ext {
libraryDesc = "Delegates for kotlin on android that check UI thread"
}
apply from: '../publish.gradle' // Makes this library publishable
When you have all of this setup properly, with the name of your library instead of mine's (which you can use as an example), you can try publishing a version of your flavored library by trying to first publishing to mavenLocal.
To do so, run this command:
myLibrary $ ../gradlew publishToMavenLocal
You can then try adding mavenLocal in your app's repositories (example here) and try adding your library as a dependency (artifactId should be the flavor name, with "_" replaced with "-") and building it.
You can also check with your file explorer (use cmd+shift+G on Mac in Finder to access hidden folder) the directory ~/.m2 and look for your library.
When it's time to publish to bintray/jcenter, you just have to run this command:
myLibrary $ ../gradlew bintrayUpload
Important:
Before you publish your library to mavenLocal, Bintray or another maven repository, you'll usually want to try your library against a sample app which uses the library. This sample app, which should be another module in the same project just need to have the project dependency, which should look like this: compile project(':myLibrary'). However, since your library has multiple productFlavors, you'll want to test all of them. Unfortunately, it's currently impossible to specify which configuration you want to use from your sample app's build.gradle file (unless, you use publishNonDefault true in your library's build.gradle file, which breaks maven and bintray publications), but you can specify the default configuration (i.e. buildVariant) in your library's module as such: defaultPublishConfig "myLibraryDebug" in the android closure. You can see the available build variants for your library in the "Build Variants" tool Windows in Android Studio.
Feel free to explore my library "Splitties" here if you need an example. The flavored module is named concurrency, but I use my script for unflavored library modules too, and I tested it throughly on all the library modules in my project.
You can reach me out if you need help setting it up for you.
The setup:
buildTypes {
debug {
}
release {
}
}
publishNonDefault true
The fix:
defaultPublishConfig 'release'
// Fix for defaultPublishConfig not working as expected
// ref: https://github.com/dcendents/android-maven-gradle-plugin/issues/11
libraryVariants.all { variant ->
if( publishNonDefault && variant.name == defaultPublishConfig ) {
def bundleTask = tasks["bundle${variant.name.capitalize()}"]
artifacts {
archives(bundleTask.archivePath) {
classifier null //necessary to get rid of the suffix in the artifact
builtBy bundleTask
name name.replace('-' + variant.name, '')//necessary to get rid of the suffix from the folder name
}
}
}
}
This fix will still publish all the artifacts, but it will publish a default artifact without the flavour suffix, which is enough to make it all work.
The fix to upload only the default artifact would be this (if the bintray plugin knew what POM filters are):
install {
repositories.mavenInstaller {
/*
POM filters can be used to block artifacts from certain build variants.
However, Bintray does not respect POM filters, therefore this only works for maven deploy plugin.
Also, bintray crashes with named filters, since it always expects a /build/pom/pom-default.xml,
which does not happen with named filters.
*/
filter { artifact, file ->
// this how the default classifier is identified in case the defaultPublishConfig fix is applied
artifact.attributes.classifier == null
}
}
}
I didn't try it so I will delete the answer if it doesn't resolve the issue.
You should post a different artifact for each flavor (or build variant if you prefer).
In this way you will have in jcenter x artifacts, each of them with a pom file.
Something like:
groupId
|--library-full
|----.pom
|----.aar
|--library-light
|----.pom
|----.aar
In your top level file you can define
allprojects {
repositories {
jcenter()
}
project.ext {
groupId="xxx"
libraryName = ""
......
}
}
Then in your library module:
productFlavors {
full {
project.ext.set("libraryName", "library-full");
}
light {
project.ext.set("libraryName", "library-light");
}
}
bintray {
//...
pkg {
//...Do the same for other variables
name = project.ext.libraryName
}
}
Finally make sure to publish only the release build type (why also the debug version?)
If someone is still stuck with this problem here's what worked for me -
Let's say you want to publish the release build for your flavour1 add this to your build.gradle
android {
...
defaultPublishConfig "flavour1Release"
}
Remove publishNonDefault true if it is present in your gradle file.
Add this inside the bintray block like this
bintray {
...
archivesBaseName = 'YOUR_ARTIFACT_ID'
...
}
Then just run the bintrayUpload task as you would.
The defaultPublishConfig will have to be changed everytime you need to publish a new flavour.
It sounds like you don't want the classifier in the filename. It looks like the classifier is the same as the generated library file name. Have you tried giving them the same filename but outputting them to separate directories?
E.g. in the android scope:
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "same_name-${version}.aar"
output.outputFile = new File(outputFile.parent+"/${archivesBaseName}", fileName)
}
}
}
I'm in the early stages of migrating an android project to gradle, using the experimental plugin 0.4.0
As part of the build process I have a number of scripts that should run prior to compiling my code / building the apk. The arguments or tasks themselves will be different for a debug or release build.
I'm struggling to find a straight forward way to achieve this.
I've stripped everything back to a simple hello world project while I figure this out.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.4.0'
}
}
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
}
android.buildTypes {
debug {
//
}
release {
//runProguard, sign etc.
}
}
android.productFlavors {
create("free")
{
applicationId = "com.example.app.free"
versionName = "1.0-free"
}
create("full")
{
applicationId = "com.example.app.full"
versionName = "1.0-full"
}
}
}
repositories {
jcenter()
}
dependencies {
compile 'joda-time:joda-time:2.7'
}
task runScript(type: Exec) {
executable "sh"
args "-c", "echo SomeScriptHere"
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn runScript
}
task wrapper(type: Wrapper) {
gradleVersion = '2.5'
}
Ideally I want to differentiate by buildType ( not productFlavor ) as the tasks required as based on the type of build not the variety of app produced.
Is it possible to specify that a task should only run on a release or debug build?
Alternatively is it possible to define different arguments to be used for my runScript task based on being a release or debug build?
Apologies if I'm missing something obvious, I'm pretty new to using gradle.
using onlyIf() would be one option gradle docs here but having to define properties seemed awkward especially as a project gets larger and more complicated.
ZXStudio has a good blog post / example here where instead of using properties or rules will iterate over the existing tasks and create a new task based on the buildType / flavor.
So for my original question the answer mean removing the runScript task above and replacing tasks.withType(JavaCompile) as follows;
Could also be extended to match build flavors and create tasks appropriately.
tasks.withType(JavaCompile) {
def newTaskName = "runScript_" + name;
def isDebug = false;
if( name.contains("Debug") )
{
isDebug = true;
}
//Create a new task
tasks.create( newTaskName, Exec ) {
if( isDebug )
{
executable "sh"
args "-c", "echo this is a DEBUG task"
}
else
{
executable "sh"
args "-c", "echo this is a RELEASE task"
}
}
dependsOn newTaskName
}
I have a project with several modules in it one of which is a Android Library named (poorly) as sdk. When I build the project it outputs an AAR named sdk.aar.
I haven't been able to find anything in the Android or Gradle documentation that allows me to change the name of the AAR output. I would like it to have a basename + version number like the Jar tasks do, but I can't work out how to do the same for the AAR because all the config for it seems to be hidden in the android.library plugin.
Renaming the module isn't an option at this stage and that still wouldn't add the version number to the final AAR.
How can I change the name of the AAR generated by com.android.library in Gradle?
Gradle solution
defaultConfig {
minSdkVersion 9
targetSdkVersion 19
versionCode 4
versionName '1.3'
testFunctionalTest true
project.archivesBaseName = "Project name"
project.version = android.defaultConfig.versionName
}
As mentioned in comments below and another answer, the original answer here doesn't work with Gradle 3+. Per the docs, something like the following should work:
Using the Variant API to manipulate variant outputs is broken with the
new plugin. It still works for simple tasks, such as changing the APK
name during build time, as shown below:
// If you use each() to iterate through the variant objects,
// you need to start using all(). That's because each() iterates
// through only the objects that already exist during configuration time—
// but those object don't exist at configuration time with the new model.
// However, all() adapts to the new model by picking up object as they are
// added during execution.
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
OLD ANSWER:
I am unable to get archivesBaseName & version to work for me w/ Android Studio 0.8.13 / Gradle 2.1. While I can set archivesBaseName and version in my defaultConfig, it doesn't seem to affect the output name. In the end, adding the following libraryVariants block to my android {} scope finally worked for me:
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${archivesBaseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
For Android Studio 3 with Gradle 4 and Android Plugin for Gradle 3.0.0 you have to change the answer of qix to the following:
android {
...
libraryVariants.all { variant ->
variant.outputs.all { output ->
if (outputFile != null && outputFileName.endsWith('.aar')) {
outputFileName = "${archivesBaseName}-${version}.aar"
}
}
}
}
In my case, ${version} result in "unspecified", finnally I found ${defaultConfig.versionName} works.
android {
...
libraryVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${defaultConfig.versionName}.aar"
}
}
}
with the build-plugin 1.5.0 it is now possible to use archivesBaseName in the defaultConfig
For the latest version of Gradle 5+, this is the best answer following #frouo answer:
defaultConfig {
...
versionName "some-version-name-or-number"
setProperty("archivesBaseName", "${archivesBaseName}-$versionName")
...
}
AAR extension will be added automatically.
In addition to qix answer here the info that you can add multiple output paths by this method by an regular string as well:
libraryVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.aar')) {
def fileName = "${archivesBaseName}-${version}.aar"
output.outputFile = new File(outputFile.parent, fileName)
output.outputFile = new File("/home/pepperonas/IdeaProjects/Libraries/Base/testapp/libs", fileName)
}
}
}
(Upvotes belong to qix - I just wrote this as an answer because of the readability).
Using Gradle 6+ and AGP 4+, an alternative answer that allows full control of the name is:
afterEvaluate {
android.libraryVariants.all { variant ->
variant.variantData.outputFactory.apkDataList.each { apkData ->
if (apkData.outputFileName.endsWith('.aar')) {
apkData.outputFileName = "${project.name}-${buildType.name}-anything-you-want.aar"
}
}
}
}
For Gradle 5+:
android.libraryVariants.all { variant ->
variant.variantData.outputFactory.output.apkDatas.each { apkData ->
apkData.outputFileName = "YourNewFileName.aar"
}
}
For Gradle 4+:
android.libraryVariants.all { variant ->
variant.outputs.each { output ->
output.outputFileName = "YourNewFileName.aar"
}
}
For Gradle 2+ and Gradle 3+:
android.libraryVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(file.parent, "YourNewFileName.aar")
}
}
I'm trying to list all of mine Android Gradle project's actual dependencies in the BuildConfig.java (see How to determine during the build which exactly version of dependency is used). For that I'm using code similar to this:
def getProjectAndBuildscriptDependencies() {
project.allprojects.collectMany{ proj ->
def configurations = (proj.configurations + proj.buildscript.configurations)
configurations.collectMany { it.allDependencies }
}.findAll { it instanceof ExternalDependency }
}
private def resolveActualDependencyVersion(Dependency dependency) {
def version = dependency.version
boolean mightBeDynamicVersion = version != null && (version.endsWith('+') || version.endsWith(']') || version.endsWith(')') || version.startsWith('latest.'))
if (!mightBeDynamicVersion){
return version
}
def actualVersion = resolveWithAllRepositories{
project.configurations.detachedConfiguration(dependency).resolvedConfiguration.lenientConfiguration
.getFirstLevelModuleDependencies(org.gradle.api.specs.Specs.SATISFIES_ALL).find()?.moduleVersion ?: version
}
return actualVersion
}
This function is supposed to gather all the dependencies I have. If I call it from some task, it does what it has to:
task printCurrentDependencies << {
def current = getProjectAndBuildscriptDependencies()
def currentVersions = [:]
current.each { dependency ->
def actualVersion = resolveActualDependencyVersion(dependency)
currentVersions.put(keyOf(dependency), actualVersion)
}
}
So that currentVersions contain all the dependencies with their actual version.
However when I call it from defaultConfig of android section, it only gives me one dependency, which is the Gradle itself.
android {
defaultConfig {
buildConfigField "int", "depsCount", getProjectDependencies().size().toString()
}
}
This difference in behavior is confusing me. Why this happens, and how to fix it and achieve what I really want?