I have created a default Empty Views Activity project in Android Studio with Kotlin as language and Kotlin DSL as build configuration language. Then I appended the following code to the app level build.gradle.kts
.
abstract class CustomTask : DefaultTask() {
@get:Input
var generatedCodePath = ""
@TaskAction
fun run() {
val path = File(generatedCodePath).resolve(
"custom_code/debug/out/com/example/app/CustomCode.kt"
)
path.parentFile.mkdirs()
path.writeText("""
#package com.example.app
#
#public fun customCode() {
# println("Hello from custom code!")
#}
""".trimMargin("#"))
}
}
tasks.register<CustomTask>("customTask") {
generatedCodePath = "$buildDir/generated"
}
tasks.named("preBuild").configure {
dependsOn("customTask")
}
The idea is that the new CustomTask
will generate a file on each build. After sync & rebuild I have checked that indeed the file CustomCode.kt
has been correctly generated in app\build\generated\custom_code\debug\out\com\example\app\CustomCode.kt
.
Now I have tried to import the function customCode
from the generated file to the MainActivity
but I have run into unresolved references.
package com.example.gradlegenerate
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.app.* // Unresolved reference: app
import com.example.app.CustomCodeKt // Unresolved reference: app
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Note that the generated file is in package app
and the activity in gradlegenerate
so there is no name collision.
I tried to add the generated file in the source sets in app level build.gradle.kts
and repeat the sync & rebuild & import but no luck.
android {
sourceSets {
named("main") {
java.srcDir("$buildDir/generated/debug/out")
}
}
}
What am I missing?
The problem was that the path of the generated code did not match the path added to the source sets.
In app/build.gradle.kts
I've corrected the source sets.
sourceSets {
named("main") {
java.srcDir("$buildDir/generated/custom_code/debug/out")
}
}
Note the string custom_code
that was missing in the question text.
Now I could finally import and use the customCode
function in the MainActivity.
package com.example.gradlegenerate
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.app.customCode
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
customCode()
}
}
When I build and run the app the output is then registered by Logcat.
System.out com.example.gradlegenerate I Hello from custom code!