I'm implementing ktor in Android inside a library ...
# ktor
h
I'm implementing ktor in Android inside a library and want to build it as an AAR file. When using that AAR to fetch data from API with ktor, I got ANR and this warning show up in logcat.
Copy code
Rejecting re-init on previously-failed class java.lang.Class<com.example.NetworkConfigKt>: java.lang.NoClassDefFoundError: Failed resolution of: Lio/ktor/client/engine/android/Android;
                                                                                                      (Throwable with no stack trace)
                                                                                                      Caused by: java.lang.ClassNotFoundException: Didn't find class "io.ktor.client.engine.android.Android" on path: DexPathList
I've read this issue and I need to implement ktor-related dependencies to main app to let it work correctly.
Copy code
implementation 'io.ktor:ktor-client-android:1.5.0'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0'
implementation 'io.ktor:ktor-client-logging-jvm:1.5.0'
implementation 'io.ktor:ktor-client-serialization:1.5.0'
I have the same question with the github issue, how do we use ktor without manually putting several implementations manually like above?
a
contents of
build.gradle.kts
?
h
@andylamax this is gradle file of library module.
Copy code
plugins {
    alias(libs.plugins.androidLibrary)
    alias(libs.plugins.jetbrainsKotlinAndroid)
    id("com.google.devtools.ksp") version "1.9.21-1.0.15"
    kotlin("plugin.serialization") version "1.9.22"
}

android {
    namespace = "com.example"
    compileSdk = 34

    defaultConfig {
        minSdk = 24

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles("<http://consumer-rules.pro|consumer-rules.pro>")
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "<http://proguard-rules.pro|proguard-rules.pro>"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    buildFeatures {
        compose = true
    }
    composeOptions {
        kotlinCompilerExtensionVersion = "1.5.1"
    }

}

dependencies {
    implementation(libs.androidx.material3)
    implementation(libs.androidx.activity.compose)
    implementation(libs.androidx.ui.android)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.lifecycle.runtime.compose)
    api(libs.ktor.client.android)
    api(libs.ktor.client.serialization)
    api(libs.kotlinx.serialization.json)
    api(libs.ktor.client.logging.jvm)
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.appcompat)
    implementation(libs.material)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
}
If I import the library project instead of building AAR, it works fine.
a
And contents of your libs file??
I just need to be sure that
ktor.client.android
is indeed an alias of
io.ktor:ktor-client-android
h
@andylamax here is the version catalogue file
gradle/wrapper/libs.versions.toml
Copy code
[versions]
agp = "8.3.1"
firebaseBom = "30.3.1"
kotlin = "1.9.0"
coreKtx = "1.12.0"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
kotlinxSerializationJson = "1.6.3"
ktorClientAndroid = "1.5.0"
ktorClientLoggingJvm = "1.5.0"
ktorClientSerialization = "1.5.0"
lifecycleRuntimeKtx = "2.7.0"
activityCompose = "1.8.2"
composeBom = "2023.08.00"
appcompat = "1.6.1"
material = "1.11.0"
koin-bom = "3.5.3"
uiAndroid = "1.6.5"
googleServices = "4.3.15"
firebaseCrashlyticsVersion = "2.9.8"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleRuntimeKtx" }
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
firebase-auth = { module = "com.google.firebase:firebase-auth-ktx" }
firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" }
firebase-analytics = { module = "com.google.firebase:firebase-analytics-ktx" }
firebase-notification = { module ="com.google.firebase:firebase-messaging" }
firebase-remoteConfig = { module ="com.google.firebase:firebase-config-ktx" }
firebase-dynamicLinks = { module ="com.google.firebase:firebase-dynamic-links-ktx" }
firebase-firestore = { module ="com.google.firebase:firebase-firestore-ktx" }
firebase-performance = { module ="com.google.firebase:firebase-perf-ktx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktorClientAndroid" }
ktor-client-logging-jvm = { module = "io.ktor:ktor-client-logging-jvm", version.ref = "ktorClientLoggingJvm" }
ktor-client-serialization = { module = "io.ktor:ktor-client-serialization", version.ref = "ktorClientSerialization" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
koin-bom = { module = "io.insert-koin:koin-bom", version.ref = "koin-bom" }
koin-core = { module = "io.insert-koin:koin-core" }
koin-android = { module = "io.insert-koin:koin-android" }
androidx-ui-android = { group = "androidx.compose.ui", name = "ui-android", version.ref = "uiAndroid" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
googleServices = {id = "com.google.gms.google-services", version.ref = "googleServices" }
firebaseCrashlytics = {id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlyticsVersion" }
and sure, that is
io.ktor:ktor-client-android
a
Your library
build.gradle.kts
and
libs.version.toml
looks fine. Lastly, show the contents of
build.gradle.kts
of the app that consumes this library
h
@andylamax here is the build.gradle file, it is long so i put it in a gist
Copy code
<https://gist.github.com/kainjinez/b4b7f80f8d7708e9044751ad9d18ab70>
a
Can you make sure that you use the same version of Ktor across the project and use the latest stable version of Ktor 2.3.10?
h
@Aleksei Tirman [JB] Before your question, I used 1.5.0. After that, I upgraded to 2.3.10 but it is still showing error. Noted that I only use ktor inside this lib, nowhere else. If I implement ktor lib in main app and it works well, but I want to prevent that. The ktor version should rely on ktor in library, not by main app.
I see that AAR won't include dependencies by default. Just keep a reference only. But why ktor is the only library that when using inside a lib, we have to implement the same on the main app? Since we don't know the actual version of ktor in the library, how do we configure outside correctly with the same to prevent version mismatch?
a
It's difficult to answer. Can you please file an issue with a sample project attached to reproduce the problem?
h
@Aleksei Tirman [JB] I filed an issue KTOR-6969. Hope you can check the sample project.
👍 1