I was experimenting with my project's build.gradle. Currently my project consist of several modules, each of these module have common dependencies, such as android support or network library. I'm Experimenting with gradle dependencies.
I've declared a group of dependencies named lib_mandatory() in file lib-group.gradle, but when I tried to include it in my app's build.gradle the gradle sync failed.
Error:Could not find method lib_mandatory() for arguments [] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
How can I fix this? or any hints about what this error means?
Update:
Here's the lib-group.gradle
def dependencyGroup(Closure closure) {
closure.delegate = dependencies
return closure
}
def lib_mandatory = dependencyGroup{
implementation libraries.rxjava
implementation libraries.rxandroid
}
and here's the app's build.gradle
apply from: '../lib-group.gradle'
dependencies {
lib_mandatory()
}
The approach that is used in that article is a bit different, the article used the function inside the lib-group.gradle and only applied (apply from ...) the lib-group.gradle in the app's build.gradle.
In your approach, you're trying to use the function in the app's build.gradle.
If you want your functions to be accessed from other files, you should use ext instead of def. You might want to read this:
Gradle def vs ext
Related
I have read the other threads on this but still can't get it to work.
I've added,
def nav_version = "2.3.5"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
To the Project Gradle, and:
id 'androidx.navigation.safeargs'
To the app Gradle file.
I have:
android.useAndroidX=true
android.enableJetifier=true
in the gradle.properties file
I've followed the tutorials to the letter, adding argument but still I don't get the direction or any other classes generated once I rebuild the project.
What am I missing?
Maybe you are using kotlin (as infered from your tags) and an alternative way is to use the plugin for Safe Args just in Kotlin:
build.gradle (:project):
buildscript {
ext.nav_version = "2.3.5"
dependencies {
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}
build.gradle (:app):
plugins {
id 'androidx.navigation.safeargs.kotlin'
}
Verify:
Kotlin >= 1.4
Android Studio >= 4.2.
Ok, the answer was found, thanks to #anshul:
The problem is not that the files are not generated, they are.
But, the IDE does not find them. As I am using Kotlin, the answer is a bit different from that for Java.
You must add to your app-level Gradle
android {
...
sourceSets {
main {
kotlin {
// srcDirs += 'build/generated/source/navigation-args/'
srcDirs += 'build/generated/source/navigation-args/debug/com/example/navanddata/ui/'
}
}
In my IDE, if you use the first (commented out) line, you get a multitude of folders that appear in your IDE sidebar. But if you go for the second, you must update it to your project name and update it for DBG / REL compilation.
In both cases, you will have to look for the files for a bit as they do not appear where you would expect, rather (in the second option) under a folder called Kotlin are “root level”.
Is there a way to leverage the new functions withSourcesJar() and withJavadocJar() for Android library projects? Currently when I try to use it I get:
> SourceSet with name 'main' not found.
With the latest Gradle version 6.0.1, there seems to be no way to use these new methods in Android library projects. Here’s why I believe that’s the case:
The two methods withJavadocJar() and withSourcesJar() on the java extension have the default main source set hardcoded, see here and here.
There are two methods with the same names (withJavadocJar() and withSourcesJar()) which can be used in feature variant declarations. However, it seems that Android Gradle builds don’t use feature variants, i.e., these methods can’t be used either.
The documentation states, that these come from the JavaPluginExtension - but not from Android DSL. So they can only be used in conjunction with apply plugin: "java" or apply plugin: "java-library", but not with apply plugin: "com.android.application", apply plugin: "com.android.library" and alike. The name of these tasks also suggest that it's common Java (*.jar) and not Android (*.aar). On Android, this would only make sense for a *.jar library, which uses pure Java features, but no Android features at all (which is limited in functionality).
In short, apply plugin: "java-library" would permit accessing these.
With Gradle 7.2 I "recreated" withJavadocJar and withSourcesJar using Gradle Kotlin DSL:
val sourceFiles = android.sourceSets.getByName("main").java.getSourceFiles()
tasks.register<Javadoc>("withJavadoc") {
isFailOnError = false
dependsOn(tasks.named("compileDebugSources"), tasks.named("compileReleaseSources"))
// add Android runtime classpath
android.bootClasspath.forEach { classpath += project.fileTree(it) }
// add classpath for all dependencies
android.libraryVariants.forEach { variant ->
variant.javaCompileProvider.get().classpath.files.forEach { file ->
classpath += project.fileTree(file)
}
}
source = sourceFiles
}
tasks.register<Jar>("withJavadocJar") {
archiveClassifier.set("javadoc")
dependsOn(tasks.named("withJavadoc"))
val destination = tasks.named<Javadoc>("withJavadoc").get().destinationDir
from(destination)
}
tasks.register<Jar>("withSourcesJar") {
archiveClassifier.set("sources")
from(sourceFiles)
}
Put this into your gradle.build.kts file and then run ./gradlew withJavadocJar and ./gradlew withSourcesJar (or use the tasks to create artifacts for publishing).
android.sourceSets.getByName("main").java.getSourceFiles() is the Android specific part to retrieve the "main" source files.
WHAT I WANT :smile: :
building kotlin library,
deliver it as an .aar file
Java project that uses my .aar don’t need configure anything, just include my .aar and start playing.
first Q : IT THAT EVEN Possible ? cause i’m loosing hope :smile:
if the project that uses my library doesn’t have Kotlin configured, then it says ClassNotFoundException.
-WHY IS THAT ?
if kotlin have the same byte code as Java byte code, (and 100% compatible),
then why i need to have kotlin when using .aar writen in kotlin in a JAVA Project ?
After some reaserch, i discovered that i must include kotlin runtime library in my project but i don’t know how,
i’ve allready tried basically all the solution overs the net ,
i think fat aar isn’t supported on Android,
Thank You All for your attention.
Update
in my aar project i have a module with the following build.gradle
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
/////
.
.
dependencies {
////
.
.
api "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
in my application that uses the .aar
i have the following in project build.gradle
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
}
in the build.gralde module
implementation(name: 'my-aar-library', ext: 'aar')
and when i run the app, it crash and here is the stack :
09-25 15:14:22.814 3239-3239/com.example.mymodule E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mymodule, PID: 3239
java.lang.NoClassDefFoundError: kotlin.jvm.internal.Intrinsics
at com.com.example.mymodule.views.MyCustomView.<init>(PCMajorHeadereView.kt)
at .
.
.
.
.
.
UPDATE 2 :
PS :
clearly i must add the kotlin runtime-library to my .aar
i tried all over the net, it doesn’t work :'(
Final Update :
solution found thanks to cilling,
note that you must include the runtime-library into the local maven repo,
it can't access online content
Thnx for all
The problem is that your aar doesn't include dependency tree (.pom file), so Gradle is not able to download them during the sync.
So, what's the proper solution? You should use repository manager, like Maven.
You can see #Robyer post how to include all dependencies and publish it on MavenLocal:
https://stackoverflow.com/a/42160584/7508302
That post is about providing source code for library, but there is also ready to use gradle publish script.
Then, in your 'local maven' a library will be published.
And then, you can add to your gradle file (in project you want to use that library): repositories { mavenLocal() } and then add dependecy like this:
implementation ('com.example.android:library:0.0.1-SNAPSHOT#aar') {
transitive = true
}
Full instruction:
1) In your library add a gradle file responsible for publishing on mavenLocal(). See https://stackoverflow.com/a/42160584/7508302 for details
and ready to use script.
2) Push the library to mavenLocal. It's a local maven repository. You don't need to install anything, as the maven repository just has to have proper dir structure.
3) Check mavenLocal dir. There should be a dir tree with your domain name, for example: com -> mycompany -> library -> 0.0.1 and in that folder you should find .pom file. Open it, to see dependencies of your library.
4) Add mavenLocal() to your repository section in project level gradle file. Note, that mavenLocal just points to some place in your files.
5) Add library dependency using just qualified name (for example: com.mycompany:library:0.0.1#aar. Add parameter transitive if you want to fetch transitive dependencies (that transitive parameter means that that library may depend on other modules).
That way gradle should fetch declared dependencies and include them to project.
Call the below call for smile.aar file in build.gradle file.
implementation project(':smile)
Assuming that smile is the .aar file name.
If you want to run Kotlin you must include following in project build.gradle
buildscript {
ext.kotlin_version = '1.3.31'
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
and also include these in app level build.gradle
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
//in dependencies
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
I have an android project with two modules. Both modules depend on android support library. Currently the support library dependency is added to gradle scripts of both modules.
When I upgrade support library version, I have to upgrade the version in both gradle files. I may sometimes forget to do this in both files. So I need a way to declare the support version in a one common place.
This page describes one approach, where you declare the dependencies in a separate file and include it in the root gradle file.
This approach worked for me, but there are some limitations. For an example, if a new support library is available, in previous approach, android studio gave me an inspection warning that a newer version is available. With new approach, android studio no longer does that. Also, whenever you make a change in a gradle file, android studio asks for re-sync the project. But, if I made change to the separated gradle dependency file, android studio doesn't ask me to re-sync.
I tried to directly add the support dependencies to the dependencies section of the root gradle file like given below, but android studio gives me a warning.
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
compile "com.android.support:appcompat-v7:23.2.1"
}
}
Warning:
Fix plugin version and sync project.
Does anyone know any other ways which I can declare dependencies in a central place?
The easiest thing to do is declare an extension variable in your buildscript block that manages the entire build. Let's take a Kotlin project, for example, where the version of kotlin must be consistent between all the build components. Here's a top-level build.gradle that defines the buildscript:
buildscript {
ext.kotlin_version = '1.0.1'
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Notice that it defines ext.kotlin_version, then uses it below in the plugin dependency.
Then, in the main app module:
dependencies {
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:design:23.2.1'
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
I can use the variable again to use the same version of the kotlin stdlib compile dependency. But I only had to define the version string in one place. ext is a special gradle way of declaring extra properties for gradle domain objects. Defining one in buildscript makes it visible elsewhere for use.
In my current setup I have two top-level Gradle projects:
A library project VideoPresenter with modules
videopresenter-common
videopresenter-exoplayer
videopresenter-visualon
where both videopresenter-exoplayer and videopresenter-visualon depend on videopresenter-common.
All three of the modules depend on OkHttp so I defined a version variable in my top-level build.gradle:
ext {
okhttp = 'com.squareup.okhttp3:okhttp:3.0.0-RC1'
}
which I use in the three other build.gradles:
dependencies {
compile rootProject.ext.okhttp
}
So far, this is completely analogous to the way, for example, RxBinding is set up. And it seems to work as long as I compile the modules from within this project.
However, I also have an application project that uses one or more of these modules. Let's say the settings.gradle of that project includes the following:
include ':videopresenter-common'
include ':videopresenter-exoplayer'
project(':videopresenter-common').projectDir = new File('../VideoPresenterAndroid/videopresenter-common')
project(':videopresenter-exoplayer').projectDir = new File('../VideoPresenterAndroid/videopresenter-exoplayer')
Now, when I try to compile the application project Gradle complains because it
Cannot get property 'okhttp' on extra properties extension as it does
not exist
presumably because rootProject now points to the top-level build.gradle of my application project.
If I add the property there the project compiles. However, I don't want to have to "inject" the correct version number from the main project into the library project. Is there a way to centrally declare the property in the library project so that it also applies when the module is imported into another project?
If the goal is to get the value from the library then you could just get the library project's rootProject then reference the ext like before. Being specific about what project we are looking for should provide the expected result.
dependencies {
compile project(':videopresenter-common').rootProject.ext.okhttp
}
As long as the project is in the settings.gradle you should be able to reference it's extension.