How to convert a common Gradle script to Gradle Kotlin DSL? - android

I am stuck on converting a common Gradle script to Gradle Kotlin DSL as it applies a custom plugin on its own so that I can't somehow make it working. What I am exactly trying to achieve this;
android-defaults.gradle (Old way - working)
apply plugin: 'libraryCommonPlugin' -> the custom plugin
android {
defaultConfig {
// other stuff
}
}
And I tried to convert this to Kotlin DSL like so;
android-default.gradle.kts (New way - not working)
plugins {
id("libraryCommonPlugin") -> the custom plugin
}
android {
defaultConfig {
// other stuff
}
}
However, this doesn't compile at all and I am getting below error;
Expression 'android' cannot be invoked as a function. The function
'invoke()' is not found
Yes, I am aware of that I don't apply com.android.application plugin but when I apply it so then I am getting another error;
Caused by: org.gradle.api.plugins.UnknownPluginException: Plugin [id:
'libraryCommonPlugin'] was not found in any of the following sources:
But I don't want to have a com.android.application plugin or whatsoever with it cause both application and library scripts will benefit from the above common script like so;
a.gradle.kts
plugins {
id("commons.android-defaults")
id("com.android.library")
id("kotlin-android")
}
dependencies {
}
app.gradle.kts
plugins {
id("commons.android-defaults")
id("com.android.application")
id("kotlin-android")
}
dependencies {
}
Do you have any solution for that particular case?

Related

Local library module dependency kotlin multiplatform

Can I include local library module on the android sourceset in kotlin multiplatform?
If so, how do we do that?
I have tried adding
api(project(":local-library-one"))
api(project(":local-library-two"))
in android source-set of build.gradle.kts file.
It fails.
You have to make your "local-library" multiplatform too. It can be only targeted to android, so you don't need to modify anything but build.gradle file, something like this:
plugins {
kotlin("multiplatform")
id("com.android.library")
}
android {
// your setup
}
kotlin {
android()
sourceSets {
val androidMain by getting {
dependencies {
// your deps
}
}
}
}

Android Gradle: Custom Plugin with id 'XXXX' not found - Kotlin DSL

I'm trying to develop a gradle plugin to use it for generating some objects and methods for our api using some scheme.
I have followed some tutorials but they all seem not to work, atleast for me.
Some of these tutorials were:
https://musings.animus.design/kotlin-poet-building-a-gradle-plugin/
https://medium.com/#magicbluepenguin/how-to-create-your-first-custom-gradle-plugin-efc1333d4419
I have not used the buildSrc module because I'm already using it for Kotlin DSL, so I decided to create a new module and create my plugin there.
My plugin's module build.gradle.kts looks like this:
plugins {
id("java-gradle-plugin")
id("kotlin")
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath(config.ClassPaths.androidBuildTools)
classpath(config.ClassPaths.kotlinGradlePlugin)
}
}
repositories {
google()
jcenter()
}
dependencies {
implementation(config.ClassPaths.androidBuildTools)
implementation(config.ClassPaths.kotlinGradlePlugin)
}
gradlePlugin {
plugins {
create("Generator") {
id = "Generator"
implementationClass = "Generator"
}
}
}
My projects settings.gradle.kts looks like this:
include(":SampleProject", ":scheme-generator")
And in my application module's build.gradle.kts I'm applying this plugin like this:
apply(plugin = "Generator")
The build script stops here with an error: plugin 'Generator' not found
My Generator class looks like this:
class Generator : Plugin<Project> {
override fun apply(target: Project) {
target.android().variants().all { variant ->
// Make a task for each combination of build type and product flavor
val myTask = "myFirstTask${variant.name.capitalize()}"
// Register a simple task as a lambda. We can later move this to its own
// class to make our code cleaner and also add some niceties.
target.tasks.create(myTask){task ->
// Group all our plugin's tasks together
task.group = "MyPluginTasks"
task.doLast {
File("${target.projectDir.path}/myFirstGeneratedFile.txt").apply {
writeText("Hello Gradle!\nPrinted at: ${SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(Date())}")
}
}
}
}
}
}
The android and variants methods are declared in a utils file, they look like this:
object GeneratorUtils {
fun Project.android(): BaseExtension {
val android = project.extensions.findByType(BaseExtension::class.java)
if (android != null) {
return android
} else {
throw GradleException("Project $name is not an Android project")
}
}
fun BaseExtension.variants(): DomainObjectSet<out BaseVariant> {
return when (this) {
is AppExtension -> {
applicationVariants
}
is LibraryExtension -> {
libraryVariants
}
else -> throw GradleException("Unsupported BaseExtension type!")
}
}
}
I have tried many things, but I seem not to get this right.
EDIT:
Using the buildSrc module for my plugin works totally fine, the plugin is applied and the gradle tasks are visible. However, buildSrc is reserved for other purposes, and we would like our plugin to be in a separate module, so we will be able to use it in other projects.
EDIT 13/04/2021
I have managed to see the tasks that are added by my plugin in my app tasks list by including this module as a composite build.
My settings.gradle now looks like this:
pluginManagement {
includeBuild("generator")
}
include(":SampleProject")
build.gradle of my plugin looks like this:
apply plugin: 'java-gradle-plugin' // Allows us to create and configure custom plugins
apply plugin: 'kotlin' //Needed as we'll write our plugin in Kotlin
buildscript {
ext {
kotlin_version = '1.4.31'
gradle_version = '4.1.2'
}
repositories {
google()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.android.tools.build:gradle:$gradle_version"
}
}
repositories {
google()
jcenter()
}
dependencies {
// Android gradle plugin will allow us to access Android specific features
}
gradlePlugin {
plugins {
create("Generator") {
id = "Generator"
implementationClass = "com.example.Generator"
}
}
}
And my generator class now looks like this:
class Generator : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register("generationTask") { task ->
task.apply {
group = "generation"
actions.add(Action {
print("Hello from generation task!")
})
}
}
}
}
I can see generationTask in my tasks list and I can execute it normally. It prints the text without any problems.
The problem now is to include com.android.tools.build:gradle:4.1.2 in my dependecies to use it to access build types and flavors and their paths to save my generated code there. When I add it to my dependencies block, gradle fails with this error: Could not find com.android.tools.build:gradle:4.1.2.
How can I solve this problem?
Gradle build goes through specific set of phases, and the Configuration phase comes before the Execution phase. So you cannot use a plugin, which is built in the same build process, because by the time gradle tries to use it on Configuration phase, the plugin has not been built yet.
buildSrc directory is a special one, it's built not as part of the same build process, but in a separate build, before the main build process starts. This feature is called included or composite build. buildSrc is just a pre-defined way to set up a composite build and you can define your own included builds. So to make your plugin visible to the main build, you need to put it into a separate build and include this build into a composite build as described in the doc above. Here is an article describing how to transform a plugin defined in buildSrc into a composite build.

Expected #HiltAndroidApp to have a value. Did you forget to apply the Gradle Plugin?

I have Google this problem, but the results are not work for me.
The detail as following.
public final class App extends com.zhixin.wedeep.common.BaseApplication implements androidx.lifecycle.LifecycleOwner {
^
// Expected #HiltAndroidApp to have a value. Did you forget to apply the Gradle Plugin?
The App code.
#HiltAndroidApp
class App : BaseApplication(), LifecycleOwner {
#Inject
lateinit var service: EventService
private val mLifecycleRegistry = LifecycleRegistry(this)
}
This module gradle file.
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-allopen'
apply plugin: 'androidx.navigation.safeargs.kotlin'
apply plugin: 'dagger.hilt.android.plugin'
dependencies {
implementation rootProject.ext.dependencies["hilt-android"]
implementation rootProject.ext.dependencies["hilt-lifecycle-viewmodel"]
kapt rootProject.ext.kapt["hilt-compiler"]
kapt rootProject.ext.kapt["hilt-android-compiler"]
}
Who has ideas? Thanks!
I just hit this problem this morning. Do you have anything in your build.gradle that adds arguments to the annotationProcessOptions? For example:
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
}
}
If so, try changing from "arguments =" to "arguments +=", as just using equals overwrites anything set previously.
EDIT: Looks like kotlin gradle plugin 1.5.21 solves the problem without using the bellow javacOptions.
UPDATE Kotlin and try again!
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21"
If you are not using Room and still get the error put this in the android block of build.gradle:
kapt {
javacOptions {
// These options are normally set automatically via the Hilt Gradle plugin, but we
// set them manually to workaround a bug in the Kotlin 1.5.20
option("-Adagger.fastInit=ENABLED")
option("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
}
}
It's a kapt bug on kotlin 1.5.20: https://github.com/google/dagger/issues/2684
SOLUTION 1 : Downgrade kotlin
If you are using kotlin-gradle-plugin:1.5.20 (in your project level build.gradle), downgrading it to 1.5.10 should fix the issue.
The issue will probably be fixed in the next versions, then you will upgrade to the new version.
SOLUTION 2 : Disable Gradle worker API
Add this line to your gradle.properties file:
kapt.use.worker.api=false
It will disable the gradle worker API.
It works for me, but as said in the documentation:
Using the worker API lets Gradle run independent annotation processing tasks from a single project in parallel, which in some cases significantly decreases the execution time.
So by disabling it, your build may be slowed down.
Just don't forget to add Hilt classpath dependency to your project level gradle file:
classpath "com.google.dagger:hilt-android-gradle-plugin:$versions.daggerHiltCoreVersion"
Define the specific version number instead of $versions.daggerHiltCoreVersion above.
And add plugin to your app level gradle:
apply plugin : 'dagger.hilt.android.plugin'
For later Gradle versions, add the plugin as follows
plugins {
id 'dagger.hilt.android.plugin'
}
Adding to sitatech's answer, I've also encountered this issue using kotlin-grade-plugin-1.5.20. The new 1.5.21 patch solved it for me.
Kotlin Grade Plugin v1.5.21 release notes: https://github.com/JetBrains/kotlin/releases/tag/v1.5.21
Issue in Jetbrains issue tracker: https://youtrack.jetbrains.com/issue/KT-47416
To backup #SteveC answer, when using Kotlin Gradle DSL is a bit different
We can't use either += or arguments = mapOf(). As stated in the official Dagger-Hilt documentation here & the github issue here regarding the docs as well
See below image for explanations:
arguments = mapOf() will call setArguments with this.arguments.clear(), thus will overwrite previous argument (in this case Hilt)
Workaround approach:
javaCompileOptions {
annotationProcessorOptions {
arguments(
mapOf(
"dagger.gradle.incremental" to "true",
"room.incremental" to "true"
)
)
}
}
Wrapping the arguments() as a functions instead of calling setter, it'll retain the previous arguments as well.
in my case, multi module in presentaion layer, I just removed :
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
}
in defaultConfig block

Expected #AndroidEntryPoint to have a value. Did you forget to apply the Gradle Plugin?

When I am using Hilt in android with Room I got this kinda error.
The full log is here:
home/someone/Desktop/Calculator/app/build/tmp/kapt3/stubs/debug/com/hamidjonhamidov/calculator/MyApplication.java:7: error: [Hilt]
public class MyApplication extends android.app.Application {
^
Expected #HiltAndroidApp to have a value. Did you forget to apply the Gradle Plugin?
[Hilt] Processing did not complete. See error above for details./home/someone/Desktop/Calculator/app/build/tmp/kapt3/stubs/debug/com/hamidjonhamidov/calculator/ui/main/MainActivity.java:7: error: [Hilt]
Anyone knows solution for this?
I had this issue after upgrading Kotlin to 1.5.20.
Adding kapt.use.worker.api=false in gradle.properties worked for me the problem
Checkout dagger issue Support for Kotlin 1.5.20
Fortunately, there is simple solution.
In build.gradle in database scheme, we should use arguments += instead of arguments = .
defaultConfig{
javaCompileOptions {
annotationProcessorOptions {
arguments += ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
Or/And in buld.gradle
You should apply plugin like:
apply plugin 'dagger.hilt.android.plugin'
This solved the problem)
UPDATE
Upgrade Hilt to v28.1.0 and Kotlin to v1.5.21 should fix this issue
OLD ANSWER
If you are on kotlin 1.5.20, answer of Mr-wil will decrease build speed as said in official doc:
To improve the speed of builds that use kapt, you can enable the
Gradle worker API for kapt tasks. Using the worker API lets Gradle run
independent annotation processing tasks from a single project in
parallel, which in some cases significantly decreases the execution
time.
Instead, set:
kapt {
javacOptions {
// These options are normally set automatically via the Hilt Gradle plugin, but we
// set them manually to workaround a bug in the Kotlin 1.5.20
option("-Adagger.fastInit=ENABLED")
option("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
}
}
source
This generic error message can also appear in many circumstances. As a more generic check, ensure that your module's build.gradle file, ensure that you has:
apply plugin: 'dagger.hilt.android.plugin'
at the top.
This was due to a bug in Kotlin 1.5.20. It is fixed in Kotlin 1.5.21.
So all you need to do is to upgrade to the latest version of Kotlin.
I had the same problem and it seems like there is a problem in kotlin-kapt plugin. If you guys have tried out all the above answers and didn't get resolved, please try the below code in your build.gradle(module-level) outside the dependencies{} block
kapt {
javacOptions {
option("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
}
}
in the build.gradle of your Android Gradle modules apply the plugin:
apply plugin: 'com.android.application'
apply plugin: 'dagger.hilt.android.plugin'
android {
// ...
}
see detail here
I'm still facing the same issue in 2022
I have solved the problem by adding
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'
to build.gradle project and adding
id 'dagger.hilt.android.plugin'
to plugins in build.gradle app
In my case it solved by declaring plugin:
plugins {
id("dagger.hilt.android.plugin")
}
Check if all these are added.In my case I had missed adding one of the below line.
In project level build.gradle
buildscript {
dependencies {
classpath "com.google.dagger:hilt-android-gradle-plugin:2.44"
}
}
In app level build.gradle
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
dependencies {
implementation "com.google.dagger:hilt-android:2.44"
implementation "androidx.hilt:hilt-common:1.0.0"
kapt "com.google.dagger:hilt-android-compiler:2.44"
}
-In app level build.gradle---add the following in newer versions
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}
In project level build.gradle
buildscript {
ext.kotlin_version = "1.7.21"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.42'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

Could not determine the dependencies of task ':app:dokka'

I'm trying to use dokka on my android project to generate kdoc.
But I have this error when I'm running the script 'modules:app [dokka]' :
Could not determine the dependencies of task ':app:dokka'.
kotlin.KotlinNullPointerException (no error message)
I added the following lines on my gradle files :
Project build.gradle
buildscript {
ext {
dokka_version = '0.9.18'
}
dependencies {
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
}
}
app build.gradle
plugins {
id 'org.jetbrains.dokka-android'
}
dokka {
outputFormat = 'html'
sourceDirs = files('src/main')
outputDirectory = "$buildDir/javadoc"
}
Could not determine the dependencies of task ':app:dokka'.
kotlin.KotlinNullPointerException (no error message)
The issue is that it's a multiplatform project. In the app level gradle file, I'm also applying the org.jetbrains.kotlin.multiplatform plugin. As described in the dokka github release page:
Experimental Kotlin Multiplatform support is scheduled for 0.9.19
Looks like there's no other solution than wait for the next release of dokka.
Edit: There's a workaround described on the kolinlang forum
dokka {
impliedPlatforms = ["common"] // This will force platform tags for all non-common sources e.g. "JVM"
kotlinTasks {
// dokka fails to retrieve sources from MPP-tasks so they must be set empty to avoid exception
// use sourceRoot instead (see below)
[]
}
sourceRoot {
// assuming there is only a single source dir...
path = kotlin.sourceSets.commonMain.kotlin.srcDirs[0]
platforms = ["common"]
}
}

Categories

Resources