KMM + Compose: Unresolved reference: drawable - android

I have a KMM application in which the android target uses Jetpack Compose. I am getting the following error when I try to use a drawable resource:
e: [...]/OnboardingScreen.kt: (33, 46): Unresolved reference: drawable
This is the result of trying to access a drawable via painterResource(id = R.drawable.ic_icon).
I have tried the following things to fix the issue:
Clean and build the project
Invalidate cache and restart
Fix all warnings when executing ./gradlew assembleDebug
The static R class is correctly imported
Nothing of the above solves the problem.
This is my build.gradle.kts of the android module:
plugins {
id("com.android.application")
kotlin("android")
}
val composeVersion = findProperty("version.compose") as String
val composeNavigationVersion = findProperty("version.composeNavigation") as String
val koinVersion = findProperty("version.koin") as String
android {
compileSdk = (findProperty("android.compileSdk") as String).toInt()
defaultConfig {
applicationId = "com.app.app.android"
minSdk = (findProperty("android.minSdk") as String).toInt()
targetSdk = (findProperty("android.targetSdk") as String).toInt()
versionCode = 1
versionName = "1.0"
}
buildFeatures {
compose = true
}
// Set both the Java and Kotlin compilers to target Java 8.
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
composeOptions {
kotlinCompilerExtensionVersion = composeVersion
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
}
dependencies {
implementation(project(":shared"))
// Android
implementation("com.google.android.material:material:1.4.0")
// Jetpack Compose
implementation("androidx.compose.ui:ui:$composeVersion")
implementation("androidx.compose.ui:ui-tooling:$composeVersion")
implementation("androidx.compose.foundation:foundation:$composeVersion")
implementation("androidx.compose.material:material:$composeVersion")
implementation("androidx.compose.material:material-icons-core:$composeVersion")
implementation("androidx.compose.material:material-icons-extended:$composeVersion")
implementation("androidx.activity:activity-compose:$composeVersion")
implementation("androidx.navigation:navigation-compose:$composeNavigationVersion")
// Koin
implementation("io.insert-koin:koin-android:$koinVersion")
}
configurations.all {
resolutionStrategy {
force("org.jetbrains.kotlin:kotlin-stdlib:1.5.31")
}
}
My build.gradle.kts of the shared module:
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
}
version = "1.0"
kotlin {
android()
iosX64()
iosArm64()
iosSimulatorArm64() // sure all ios dependencies support this target
cocoapods {
summary = "Some description for the Shared Module"
homepage = "Link to the Shared Module homepage"
ios.deploymentTarget = "14.1"
podfile = project.file("../ios/Podfile")
framework {
baseName = "shared"
}
}
val multiplatformVersion = findProperty("version.multiplatformSettings") as String
val koinVersion = findProperty("version.koin") as String
val coroutinesVersion = findProperty("version.coroutines") as String
sourceSets {
val commonMain by getting {
dependencies {
implementation("com.russhwolf:multiplatform-settings-no-arg:$multiplatformVersion")
implementation("io.insert-koin:koin-core:$koinVersion")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13.2")
}
}
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
}
val iosX64Test by getting
val iosArm64Test by getting
val iosSimulatorArm64Test by getting
val iosTest by creating {
dependsOn(commonTest)
iosX64Test.dependsOn(this)
iosArm64Test.dependsOn(this)
iosSimulatorArm64Test.dependsOn(this)
}
}
}
android {
compileSdk = 31
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 22
targetSdk = 31
}
}
And finally, my gradle.properties:
# Gradle
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
# Kotlin
kotlin.code.style=official
# Android
android.useAndroidX=true
android.compileSdk=31
android.targetSdk=31
android.minSdk=22
# MPP
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.mpp.enableCInteropCommonization=true
kotlin.native.enableDependencyPropagation=false
kotlin.native.ignoreDisabledTargets=true
# Common versions
version.multiplatformSettings=0.8.1
version.koin=3.1.4
version.coroutines=1.5.2-native-mt
# Android versions
version.compose=1.0.5
version.composeNavigation=2.4.0-rc01
Thanks in advance.

That's how you reference image resources:
import com.your.package.R
val img = R.drawable.img_name
or
val img = com.your.package.R.drawable.img_name

Denny Kurniawan's comment above pointed me in the right direction. I had a similar problem after changing the name of my project. At the top of your 'OnboardingScreen.kt' file, check to see if the full 'package' name matches your actual project's name, e.g. "package com.android.application".
If the package name listed in 'OnboardingScreen.kt' is not the same as your actual project's name, then the static R class is probably not being imported correctly and, hence, this error.
In other words, the full package name in 'OnboardingScreen.kt' should match the name of the folder shown under 'app->src->main->java'. Hope this helps someone as it did me.

for me, this error happen because I drag my image to the resource manager, I solve it by importing the images manually with the "Import Drawables" button

Related

Android Studio isn't indexing commonMain folder after adding any dependencies to its sourceSet

I'm trying to create module with shared code for Android and iOS, but when I add any dependency to commonMain it's stopping to index that folder. If I remove dependencies, everything is okay. gradlew clean doesn't help. How could I resolve this issue?
build.gradle.kts:
object Versions {
const val coroutinesVersion = "1.5.0-native-mt"
const val ktorVersion = "1.6.1"
const val kotlinVersion = "1.5.21"
const val serializationVersion = "1.2.2"
}
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
id("com.android.library")
kotlin("plugin.serialization")
}
version = "1.0"
kotlin {
android()
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.coroutinesVersion}")
implementation("io.ktor:ktor-client-core:${Versions.ktorVersion}")
implementation("io.ktor:ktor-client-serialization:${Versions.ktorVersion}")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:${Versions.serializationVersion}")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
val androidMain by getting {
dependencies {
implementation("io.ktor:ktor-client-android:${Versions.ktorVersion}")
}
}
val androidTest by getting
}
}
android {
compileSdk = 32
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
targetSdk = 32
}
}
Screen of module:
Problem was with libraries versions. After update to a newer ones everything works fine:)
Newer versions:
object Versions {
const val coroutinesVersion = "1.6.1"
const val ktorVersion = "2.0.2"
const val serializationVersion = "1.3.3"
}

Generate different artifactId when publish library in android

Hey I am publish library in kotlin multiplatform. I used this command ./gradlew clean assemble publish my three package is generated. I given the name var libraryArtifactId = "kmm-module" but I don't understand why other name is coming from.
1st package name is com.vivek.kmm-module
2nd package name is com.vivek.kotlinproject-android-debug
3rd package name is com.vivek.kotlinproject-android
I understand 1st package name, but I am not understanding where the 2nd and 3rd artificatId coming from?
build.gradle.kts
plugins {
kotlin("multiplatform") version "1.6.21"
id("com.android.library")
id("maven-publish")
}
val libraryVersion = "0.0.1"
var libraryGroup = "com.vivek"
var libraryArtifactId = "kmm-module"
repositories {
google()
mavenCentral()
}
kotlin {
android {
publishLibraryVariants("release", "debug")
}
sourceSets {
val commonMain by getting
val androidMain by getting
}
}
android {
compileSdk = 21
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
targetSdk = 31
}
#Suppress("UnstableApiUsage") compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
publishing {
publications {
group = libraryGroup
publications.withType<MavenPublication> {
groupId = libraryGroup
artifactId = libraryArtifactId
version = libraryVersion
}
repositories {
maven {
url = uri("https://maven.pkg.github.com/vivek-modi/kotlinmultiplatfromproject")
credentials {
username = (System.getenv("GITHUB_USER") ?: project.properties["GITHUB_USER"]).toString()
password = (System.getenv("GITHUB_PERSONAL_ACCESS_TOKEN") ?: project.properties["GITHUB_PERSONAL_ACCESS_TOKEN"]).toString()
}
}
}
}
}
I am adding my github repository. I used github packages for publishing library. Thanks
you can remove this line to avoid the android artifact.
android {
publishLibraryVariants("release", "debug")
}

How to configure KMM project to support different buildTypes

When I switch build variants I got compilation error, but the problem is only for non default build variants (debug & release). So if I define customBuild { } and then choose that one, it fails with this error log:
The consumer was configured to find a runtime of a component,
preferably optimized for Android, as well as attribute 'com.android.build.api.attributes.BuildTypeAttr'
with value 'customBuild', attribute 'org.jetbrains.kotlin.platform.type' with value 'androidJvm'.
However we cannot choose between the following variants of project :shared-module:
- iosArm64RuntimeOnly
- iosX64RuntimeOnly
All of them match the consumer attributes:
- Variant 'iosArm64RuntimeOnly' capability ExampleApp:shared-module:1.0:
- Unmatched attributes:
- Doesn't say anything about com.android.build.api.attributes.BuildTypeAttr (required 'customBuild')
- Doesn't say anything about its target Java environment (preferred optimized for Android)
- Doesn't say anything about its usage (required a runtime)
- Provides attribute 'org.jetbrains.kotlin.native.target' with value 'ios_arm64' but the consumer didn't ask for it
- Doesn't say anything about org.jetbrains.kotlin.platform.type (required 'androidJvm')
My build.gradle.kts for shared module
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
id("com.android.library")
id("com.squareup.sqldelight")
kotlin("native.cocoapods")
}
repositories {
gradlePluginPortal()
google()
mavenCentral()
maven {
url = uri("https://plugins.gradle.org/m2/")
}
}
version = "1.0"
kotlin {
android {
publishAllLibraryVariants()
}
ios()
cocoapods {
framework {
baseName = "core"
}
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64(),
).forEach {
it.binaries.framework {
baseName = "core"
}
}
}
targets.filterIsInstance<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget>().forEach {
it.binaries.filterIsInstance<org.jetbrains.kotlin.gradle.plugin.mpp.Framework>()
.forEach { lib ->
lib.isStatic = false
lib.linkerOpts.add("-lsqlite3")
}
}
sourceSets {
val commonMain by getting {
dependencies { ... }
}
val commonTest by getting {
dependencies { ... }
}
val androidMain by getting {
dependencies { ... }
}
val androidAndroidTestRelease by getting
val androidTest by getting {
dependsOn(androidAndroidTestRelease)
dependencies { ... }
}
val iosMain by getting {
dependencies { ... }
}
val iosTest by getting
}
}
configurations.all { }
android {
compileSdk = 30
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 21
targetSdk = 30
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
sqldelight {
database("db") {
packageName = "com.example.app.core.sqldelight"
sourceFolders = listOf("sqldelight")
schemaOutputDirectory = file("src/commonMain/sqldelight/databases")
dialect = "sqlite:3.24"
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
val framework =
kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
...
}
tasks.getByName("build").dependsOn(packForXcode)
val generateIOSArm64Framework by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "iosArm64"
val framework =
kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
inputs.property("mode", mode)
...
}
val generateIOSXCFramework by tasks.creating(Sync::class) {
dependsOn("packForXcode", "generateIOSArm64Framework")
}

Unresolved reference Issue in Android Gradle Kotlin Dsl

i migrated my gradle file to kotlin dsl from groovy. Everything works fine but there is a problem with improting values to gradle from another kotlin file. I can import variables and autocomplete just works fine but when i build project, it gives me Unresolved reference error.
Appreciate any help.
Gradle version : 7.1.1
Android studio : Arctic Fox
build.gradle.kts that i created under buildSrc :
plugins {
`java-gradle-plugin`
`kotlin-dsl`
`kotlin-dsl-precompiled-script-plugins`
}
repositories {
mavenCentral()
}
File that i import from in buildSrc/src/main/java/Dependencies :
object Versions {
const val compose_version = "1.0.0"
}
object Dependencies {
const val compose_ui = "androidx.compose.ui:ui:${Versions.compose_version}"
const val compose_material = "androidx.compose.material:material:${Versions.compose_version}"
const val compose_ui_tooling_preview = "androidx.compose.ui:ui-tooling-preview:${Versions.compose_version}"
const val compose_ui_tooling = "androidx.compose.ui:ui-tooling:${Versions.compose_version}"
const val compose_ui_test = "androidx.compose.ui:ui-test-junit4:${Versions.compose_version}"
}
app build.gradle.kts file :
plugins {
id("com.android.application")
kotlin("android")
}
android {
compileSdk = 30
defaultConfig {
applicationId = "com.example.compose"
minSdk = 21
targetSdk = 30
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
debug {
isMinifyEnabled = false
isDebuggable = true
}
release {
isMinifyEnabled = true
isDebuggable = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility(JavaVersion.VERSION_1_8)
targetCompatibility(JavaVersion.VERSION_1_8)
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.0.0"
}
packagingOptions {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
implementation("androidx.core:core-ktx:1.6.0")
implementation("androidx.appcompat:appcompat:1.3.1")
implementation("com.google.android.material:material:1.4.0")
// Jetpack Compose
implementation(Dependencies.compose_ui)
implementation(Dependencies.compose_material)
implementation(Dependencies.compose_ui_tooling_preview)
debugImplementation(Dependencies.compose_ui_tooling)
androidTestImplementation(Dependencies.compose_ui_test)
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1")
implementation("androidx.activity:activity-compose:1.3.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.3")
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
}
You said that your other file is under buildSrc/src/main/java/Dependencies. Since this is a Kotlin file, it should be buildSrc/src/main/kotlin/Dependencies instead.

Kotlin MultiPlatform - Publish Android Library Failing

Im trying to publish an Android library (debug/release) with the new Kotlin MultiPlatform set up. Im successfully able to publish iOS frameworks, but not android libraries. This is the error I end up getting:
A problem occurred configuring project ':shared'.
Failed to notify project evaluation listener.
Kotlin target 'android' tried to set up publishing for Android build variants that are not library variants or do not exist:
* release
* debug
Check the 'publishLibraryVariants' property, it should point to existing Android library variants. Publishing of application and test variants is not supported.
However, I can clearly see the variants in my Android Studio. Im also able to run the Android/IOS app from Android Studio using the library dependecy as a project dependency
implementation(project(":shared"))
Only facing problems when trying to publish it.
This is my build.gradle.kts:
plugins {
kotlin("multiplatform")
kotlin("plugin.serialization")
id("com.android.library")
id("kotlin-android-extensions")
id("com.squareup.sqldelight")
id("dev.icerock.mobile.multiplatform-resources")
`maven-publish`
}
group = "com.sekhar.testkmp"
version = "0.1"
val coroutinesVersion = "1.3.9-native-mt"
val serializationVersion = "1.0.0-RC"
val ktorVersion = "1.4.0"
val sqlDelightVersion: String by project
repositories {
gradlePluginPortal()
google()
jcenter()
mavenCentral()
}
kotlin {
android {
publishLibraryVariants("release", "debug")
}
ios {
binaries {
framework {
baseName = "shared"
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion")
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-serialization:$ktorVersion")
implementation("com.squareup.sqldelight:runtime:$sqlDelightVersion")
implementation("dev.icerock.moko:resources:0.13.1")
implementation("dev.icerock.moko:parcelize:0.4.0")
implementation("dev.icerock.moko:graphics:0.4.0")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("com.google.android.material:material:1.2.1")
implementation("io.ktor:ktor-client-android:$ktorVersion")
implementation("com.squareup.sqldelight:android-driver:$sqlDelightVersion")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.12")
}
}
val iosMain by getting {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktorVersion")
implementation("com.squareup.sqldelight:native-driver:$sqlDelightVersion")
}
}
val iosTest by getting
}
}
dependencies {
commonMainApi("dev.icerock.moko:resources:0.13.1")
}
multiplatformResources {
multiplatformResourcesPackage = "com.sekhar.testkmp" // required
}
android {
compileSdkVersion(29)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(24)
targetSdkVersion(29)
versionCode = 1
versionName = "1.0"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
getByName("debug") {
isMinifyEnabled = false
}
}
lintOptions {
isAbortOnError = false
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
val framework = kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)```
The most common solution to this is to apply the android plugin: id("com.android.library") before the kotlin multiplatform plugin: kotlin("multiplatform").
plugins {
id("com.android.library")
kotlin("multiplatform")
kotlin("plugin.serialization")
id("kotlin-android-extensions")
id("com.squareup.sqldelight")
id("dev.icerock.mobile.multiplatform-resources")
`maven-publish`
}

Categories

Resources