I am trying to develop a small library to post issues to my company's Jira server, and I thought that a Kotlin MPP w/ KTOR would be just the ticket.
At first, following a few tutorials, I made a shared project, and the imports for iOS were working fine but Android's Ktor implementation would not resolve. Then I realized that I needed to recreate the project and create a library instead of a shared application, as I have existing codebases for each mobile client already, and I need to publish the MPP library to be used by them.
Upon recreating the project as a library, and simply starting to add the dependencies for KTOR 1.3.2, the iOS dependencies are failing to resolve. This is not just KTOR, it is any iOS dependency, so there's obviously something incorrect in my project setup, but I am unable to spot it.
Here is the gradle file:
plugins {
id 'org.jetbrains.kotlin.multiplatform' version '1.3.72'
}
repositories {
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
group 'com.example.issuereporter'
version '0.0.1'
apply plugin: 'maven-publish'
kotlin {
targets {
final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos") ? presets.iosArm64 : presets.iosX64
fromPreset(iOSTarget, 'ios') {
binaries {
framework('IssueReporter')
}
}
fromPreset(presets.jvm, 'android')
}
def ktor_version = "1.3.2"
sourceSets["commonMain"].dependencies {
implementation kotlin('stdlib-common')
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
implementation "io.ktor:ktor-client-serialization:$ktor_version"
}
sourceSets["commonTest"].dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
sourceSets["androidMain"].dependencies {
implementation kotlin('stdlib')
implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
implementation "io.ktor:ktor-client-serialization-jvm:$ktor_version"
implementation "io.ktor:ktor-client-auth-jvm:$ktor_version"
}
sourceSets["androidTest"].dependencies {
implementation kotlin('test')
implementation kotlin('test-junit')
}
sourceSets["iosMain"].dependencies {
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-core-native:$ktor_version"
implementation "io.ktor:ktor-client-json-native:$ktor_version"
implementation "io.ktor:ktor-client-serialization-native:$ktor_version"
}
}
configurations {
compileClasspath
}
task packForXcode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
final def framework = kotlin.targets.ios.binaries.getFramework("IssueReporter", mode)
inputs.property "mode", mode
dependsOn framework.linkTask
from { framework.outputFile.parentFile }
into frameworkDir
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$#\n"
setExecutable(true)
}
}
}
tasks.build.dependsOn packForXcode
The console output is
Could not resolve io.ktor:ktor-client-ios:1.3.2.
Could not resolve io.ktor:ktor-client-core-native:1.3.2.
Could not resolve io.ktor:ktor-client-json-native:1.3.2.
Could not resolve io.ktor:ktor-client-serialization-native:1.3.2.
Anything obvious that I am missing here?
UPDATE
I scrapped and recreated the project w/ an updated version of IntelliJ (IntelliJ IDEA 2019.3.5 (Community Edition)) & the Kotlin 1.4.0 Plugin installed. This gave me a slightly different creation wizard, and the option to use Kotlin as the Gradle syntax.
Updated build.gradle.kts file:
plugins {
kotlin("multiplatform") version "1.4.0"
kotlin("plugin.serialization") version "1.4.0"
id("com.android.library")
id("kotlin-android-extensions")
}
group = "com.example.issuereporter"
version = "1.0-SNAPSHOT"
repositories {
gradlePluginPortal()
google()
jcenter()
mavenCentral()
maven(url = "https://kotlin.bintray.com/kotlinx")
maven(url = "https://dl.bintray.com/kotlin/ktor")
maven(url = "https://repo1.maven.org/maven2/")
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
maven(url = "https://plugins.gradle.org/m2/")
}
kotlin {
android()
iosX64("ios") {
binaries {
framework {
baseName = "library"
}
}
}
val ktor_version = "1.3.2"
val serialization_version = "0.20.0"
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.ktor:ktor-client-core:$ktor_version")
implementation("io.ktor:ktor-client-json:$ktor_version")
implementation("io.ktor:ktor-client-serialization:$ktor_version")
implementation("io.ktor:ktor-client-auth:$ktor_version")
implementation("io.ktor:ktor-client-apache:$ktor_version")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("androidx.core:core-ktx:1.2.0")
implementation("io.ktor:ktor-client-android:$ktor_version")
implementation("io.ktor:ktor-client-auth-jvm:$ktor_version")
implementation("io.ktor:ktor-client-json-jvm:$ktor_version")
}
}
val androidTest by getting
val iosMain by getting {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktor_version")
implementation ("io.ktor:ktor-client-core-native:$ktor_version")
implementation("io.ktor:ktor-client-json-native:$ktor_version")
implementation("io.ktor:ktor-client-auth-native:$ktor_version")
}
}
val iosTest by getting
}
}
android {
compileSdkVersion(29)
defaultConfig {
minSdkVersion(24)
targetSdkVersion(29)
versionCode = 1
versionName = "1.0"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
}
The gradle dependencies for iOS successfully sync when I set the ktor_version to 1.3.2 but not for 1.4.0 (assuming the mirrors haven't updated for the native files??)... but the imports don't compile when I attempt to utilize the class at all... see attached image:
I would guess you don't have enableFeaturePreview("GRADLE_METADATA") in settings.gradle.
settings.gradle
Check our starter project KaMPKit for a running example on 1.3.72. We'll probably bump that to 1.4.0 this week, but for now it should be a good reference.
Here are my dependencies (I have separate iOS targets, but it should still help you):
iosEmulatorMain.dependencies {
implementation "io.ktor:ktor-client-ios:$ktorVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutinesVersion"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serializationVersion"
implementation "com.soywiz.korlibs.klock:klock-iosx64:$klockVersion"
implementation "com.github.aakira:napier-iosX64:$napierVersion"
}
iosDeviceMain.dependencies {
implementation "io.ktor:ktor-client-ios:$ktorVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutinesVersion"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serializationVersion"
implementation "com.soywiz.korlibs.klock:klock-iosarm64:$klockVersion"
implementation "com.github.aakira:napier-iosArm64:$napierVersion"
}
Versions:
ktorVersion=1.3.2
Repositories:
maven(url = "https://kotlin.bintray.com/kotlinx")
maven(url = "https://dl.bintray.com/kotlin/ktor")
maven(url = "https://repo1.maven.org/maven2/")
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
maven(url = "https://plugins.gradle.org/m2/")
To configure client serializer try to write it like this:
install(JsonFeature) {
serializer = KotlinxSerializer(kotlinx.serialization.json.Json {
ignoreUnknownKeys = true
})
}
Related
UPDATE2: I was not generating a aar file, now it's included in the package that you can check here: https://github.com/fabrizioiacobucci/range-bar-preference/packages/787218
I see javadoc, sources and aar are there, but when I add the package as dependency in another project I don't even see it in the External Libraries.
UPDATE: This is the problem, I don't see my source files in the downloaded jar:
I recently forked a little project on Github and migrated its old code version to AndroidX and new gradle build.
After some time everything work fine and I was able also to publish the library on Git packages.
However, I tried to declare it as dependency on a different project on my local computer. It downloads fine but when I try to import it in a source file, I cannot find the package:
If I go into the project folder I see the library downloaded and related files.
This is the Project build.gradle file of the published library.
build.gradle (project)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.2.0'
classpath 'io.github.gradle-nexus:publish-plugin:1.1.0'
}
}
plugins {
id 'maven-publish'
}
apply from: "${rootDir}/scripts/publish-root.gradle"
apply plugin: 'io.github.gradle-nexus.publish-plugin'
ext {
VERSION = '1.0.0'
DESCRIPTION = 'A range bar that can be used as an android shared preference'
GROUPID = 'com.fabrizioiacobucci.android'
ARTIFACTID = 'range-bar-preference'
GITREPO = 'https://github.com/fabrizioiacobucci/tree/development/range-bar-preference.git'
PROJECTURL = 'https://github.com/fabrizioiacobucci/tree/development/range-bar-preference'
PUBLISHGIT = 1
PUBLISHMAVEN = 0
}
nexusPublishing {
repositories {
sonatype {
stagingProfileId = '1c4ab2dc896731'
//packageGroup = "com.fabrizioiacobucci.android"
username = ossrhUsername
password = ossrhPassword
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
build.gradle (module)
apply plugin: 'com.android.library'
android {
compileSdkVersion 30
buildToolsVersion '31.0.0 rc3'
defaultConfig {
minSdkVersion 14
targetSdkVersion 30
version VERSION
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
versionCode 1
versionName VERSION
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test:rules:1.3.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation 'com.appyvet:materialrangebar:1.3'
implementation 'androidx.appcompat:appcompat:1.2.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.robolectric:robolectric:4.5.1'
}
apply from: "${rootDir}/scripts/publish-module-maven.gradle"
apply from: "${rootDir}/scripts/publish-module-githubpkg.gradle"
publish-module-maven.gradle
apply plugin: 'maven-publish'
apply plugin: 'signing'
task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
}
task javadoc(type: Javadoc) {
failOnError false
source = android.sourceSets.main.java.srcDirs
classpath = configurations.compile
}
task javadocJar(type: Jar, dependsOn: javadoc) {
archiveClassifier.set('javadoc')
from javadoc.destinationDir
}
artifacts {
archives androidSourcesJar
archives javadocJar
}
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
// The coordinates of the library, being set from variables that
// we'll set up later
groupId GROUPID
artifactId ARTIFACTID
version VERSION
artifact("$buildDir/outputs/aar/range-bar-preference-release.aar")
artifact androidSourcesJar
artifact javadocJar
// Mostly self-explanatory metadata
pom {
name = 'Range Bar Preference'
description = 'A range bar that can be used as an android shared preference'
url = PROJECTURL
groupId GROUPID
licenses {
license {
name = 'The Apache Software License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution = 'repo'
}
}
developers {
developer {
id = 'FabrizioIacobucci'
name = 'Fabrizio Iacobucci'
email = 'fabrizio.iacobucci90#mail.com'
}
}
scm {
connection = 'scm:git:github.com/fabrizioiacobucci/range-bar-preference.git'
developerConnection = 'scm:git:ssh://github.com/fabrizioiacobucci/range-bar-preference.git'
url = 'https://github.com/fabrizioiacobucci/range-bar-preference/'
}
}
}
}
}
}
ext["signing.keyId"] = rootProject.ext["signing.keyId"]
ext["signing.password"] = rootProject.ext["signing.password"]
ext["signing.secretKeyRingFile"] = rootProject.ext["signing.secretKeyRingFile"]
signing {
sign publishing.publications
}
publish-module-githubpkg.gradle
artifacts {
archives androidSourcesJar
archives javadocJar
}
project.publishing {
publications {
maven(MavenPublication) {
groupId = GROUPID
artifactId = ARTIFACTID
version = VERSION
artifact("$buildDir/outputs/aar/range-bar-preference-release.aar")
artifact androidSourcesJar
artifact javadocJar
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
}
usage('java-runtime') {
fromResolutionResult()
}
}
pom {
name = 'Range Bar Preference'
packaging = 'aar'
description = 'A range bar that can be used as an android shared preference'
url = PROJECTURL
licenses {
license {
name = 'The Apache Software License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution = 'repo'
}
}
developers {
developer {
id = 'FabrizioIacobucci'
name = 'Fabrizio Iacobucci'
email = 'fabrizio.iacobucci90#mail.com'
}
}
scm {
connection = 'scm:git:github.com/fabrizioiacobucci/range-bar-preference/range-bar-preference.git'
developerConnection = 'scm:git:ssh://github.com/fabrizioiacobucci/range-bar-preference/range-bar-preference.git'
url = 'https://github.com/fabrizioiacobucci/range-bar-preference/'
}
}
}
}
repositories {
maven {
name = "GitHubPackages"
url = uri('https://maven.pkg.github.com/fabrizioiacobucci/range-bar-preference')
credentials {
username = System.getenv("GITHUB_USER")
password = System.getenv("GITHUB_TOKEN")
}
}
}
}
I don't know if there is anything else relevant to share, please let me know in case.
Do you have any idea what am I missing?
Thanks a lot in advance for any help.
As promised I forked the original project upgraded to android and then all the dependencies to the latest.
For the fast release of SDK to do the POC, I released it to jitpack.io
How to add the new library as a dependency.
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Add this to your app module dependencies:
dependencies {
implementation 'com.github.dk19121991:range-bar-preference:0.0.7'
}
I did try it myself and it's working fine for me, I updated the app module in my forked version to use the library from jitpack only, and it's working smoothly.
Please try the library and let me know if you feel anything else you need.
https://github.com/dk19121991/range-bar-preference
import com.nfx.android.rangebarpreference
change fabrizioiacobucci to nfx will solve your poblem
Every time I publish a Kotlin Multiplatform Mobile library to maven central the only I can seem to add/use the Android dependency in an Android app is by adding both the releaseImplementation and debugImplementation
Example
releaseImplementation 'io.github.tyczj.lumberjack:Lumberjack-android:1.0.0#aar'
debugImplementation 'io.github.tyczj.lumberjack:Lumberjack-android-debug:1.0.0#aar'
Instead of the "normal" way where you just have a single implementation
implementation 'io.github.tyczj.lumberjack:Lumberjack-android:1.0.0'
Here is my build.gradle file
plugins {
kotlin("multiplatform") version "1.4.32"
id("com.android.library")
id("io.github.gradle-nexus.publish-plugin") version "1.1.0"
id("maven-publish")
id("signing")
}
group = "io.github.tyczj.lumberjack"
version = "1.0.2"
ext["signing.keyId"] = ""
ext["signing.password"] = ""
ext["signing.secretKeyRingFile"] = ""
repositories {
google()
mavenCentral()
maven {
setUrl("https://plugins.gradle.org/m2/")
}
}
val javadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
}
val emptyJar by tasks.registering(Jar::class) {
archiveAppendix.set("empty")
}
kotlin {
android{
publishLibraryVariants("release", "debug")
}
iosX64("ios") {
binaries {
framework {
baseName = "lumberjack"
}
}
}
sourceSets {
val commonMain by getting
val commonTest by getting
val androidMain by getting
val androidTest by getting
val iosMain by getting
val iosTest by getting
}
}
android {
compileSdkVersion(29)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(24)
targetSdkVersion(29)
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
}
afterEvaluate {
publishing {
repositories {
maven {
name = "sonatype"
url = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = rootProject.ext["ossrhUsername"]?.toString()
password = rootProject.ext["ossrhPassword"]?.toString()
}
}
}
publications.withType<MavenPublication> {
artifact(javadocJar.get())
pom{
name.set("Lumberjack")
description.set("Logging library for Kotlin Multiplatform Mobile applications")
url.set("https://github.com/tyczj/Lumberjack")
licenses {
license {
name.set("MIT")
url.set("https://opensource.org/licenses/MIT")
}
}
developers {
developer {
id.set("tyczj")
name.set("Jeff Tycz")
email.set("tyczj359#gmail.com")
}
}
scm {
url.set("https://github.com/tyczj/Lumberjack")
}
}
}
}
}
ext["signing.keyId"] = rootProject.ext["signing.keyId"]?.toString()
ext["signing.password"] = rootProject.ext["signing.password"]?.toString()
ext["signing.secretKeyRingFile"] = rootProject.ext["signing.secretKeyRingFile"]?.toString()
signing {
sign(publishing.publications)
}
apply(from = "${rootDir}/scripts/publish-root.gradle")
The full source for this library can be found here
What is wrong with how I am building/publishing KMM libraries where I have to specify the release and debug implementations?
You should not specify -android postfix, just use implementation("io.github.tyczj.lumberjack:Lumberjack:1.0.0").
This works because dependency variant resolution is based on Gradle Module Metadata. This metadata is just another file published with your library (it has .module extension) and it contains description of all variants. As you are publishing the library as a whole, the top-level artifact io.github.tyczj.lumberjack:Lumberjack contains the metadata for the whole library, allowing gradle to choose the right variant.
Another option would be to make sure your -android artifact contains proper module metadata with both release and debug variants. I believe publishLibraryVariantsGroupedByFlavor is the way to tell the publisher plugin to make it this way, but I have not tried it.
My build.gradle.kts(:app):
plugins {
id("com.android.application")
kotlin("plugin.serialization") version "1.4.21-release-Studio4.2-1"
kotlin("android")
kotlin("android.extensions")
kotlin("kapt")
}
android {
compileSdkVersion (30)
buildToolsVersion ("30.0.2")
defaultConfig {
applicationId ="learnprogramming.academy.relaf"
minSdkVersion(24)
targetSdkVersion(30)
versionCode =1
versionName ="1.0"
testInstrumentationRunner ="androidx.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments["room.incremental"] = "true"
}
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}
buildFeatures {
// Enables Jetpack Compose for this module
compose = true
}
compileOptions {
sourceCompatibility= JavaVersion.VERSION_1_8
targetCompatibility= JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
useIR = true
}
composeOptions {
kotlinCompilerVersion= "1.4.21-release-Studio4.2-1"
kotlinCompilerExtensionVersion= "1.0.0-alpha08"
}
}
dependencies {
val composeVersion = "1.0.0-alpha08"
// implementation ("androidx.compose.runtime:runtime:$composeVersion")
// implementation ("androidx.compose.compiler:compiler:$composeVersion")
// implementation ("androidx.compose.ui:ui:$composeVersion")
// Tooling support (Previews, etc.)
implementation ("androidx.compose.ui:ui-tooling:$composeVersion")
// Foundation (Border, Background, Box, Image, Scroll, shapes, animations, etc.)
implementation ("androidx.compose.foundation:foundation:$composeVersion")
// Material Design
implementation ("androidx.compose.material:material:$composeVersion")
// Material design icons
implementation ("androidx.compose.material:material-icons-core:$composeVersion")
implementation ("androidx.compose.material:material-icons-extended:$composeVersion")
// Integration with observables
implementation ("androidx.compose.runtime:runtime-livedata:$composeVersion")
val roomVersion = "2.3.0-alpha04"
implementation( "androidx.room:room-runtime:$roomVersion")
kapt ("androidx.room:room-compiler:$roomVersion")
val kotlin_version = "1.4.21"
implementation ("org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version")
implementation( "androidx.appcompat:appcompat:1.3.0-alpha02")
testImplementation ("junit:junit:4.12")
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
// optional - Kotlin Extensions and Coroutines support for Room
implementation ("androidx.room:room-ktx:$roomVersion")
// ViewModel and LiveData
val lifecycle_version = "2.2.0"
implementation ("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
implementation ("androidx.lifecycle:lifecycle-extensions:$lifecycle_version")
implementation ("androidx.fragment:fragment-ktx:1.2.2")
// RecyclerView
implementation ("androidx.recyclerview:recyclerview:1.0.0")
implementation ("com.google.android.material:material:1.3.0-alpha03")
implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9")
implementation ("com.android.volley:volley:1.1.1")
implementation("org.jsoup:jsoup:1.13.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
implementation ("androidx.core:core-ktx:1.0.2")
implementation ("androidx.constraintlayout:constraintlayout:1.1.3")
androidTestImplementation ("androidx.test.ext:junit:1.1.0")
androidTestImplementation( "androidx.test.espresso:espresso-core:3.1.1")
}
My other build.gradle.kts (Top 10 Downloader):
buildscript {
val kotlin_version = "1.4.21"
repositories {
google()
jcenter()
}
dependencies {
classpath ("com.android.tools.build:gradle:7.0.0-alpha03")
classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
tasks.register("clean",Delete::class){
delete(rootProject.buildDir)
}
my settings.gradle.kts:
include (":app")
rootProject.name="Top 10 Downloader"
It is reproducible in an empty project. I'm using latest canary android studio arctic fox. What I am doing wrong?
ok bug found. Latest canary android studio updated my gradle version and because of gradle update, buildFeatures { compose = true } in build.gradle causes gradle to run forever because i was using kotlin synthetics which is now deprecated. So in latest gradle (7), USING synthetics (not just adding) and IMPORTINGbuildFeatures { compose = true }causes gradle infinite loop.
I was able to resolve this error by disabling gradle offline mode.
I tried to integrate sqldelight in my Multiplatform library project for Android/iOS but I'm having several unresolved dependency errors when syncing gradle.
ERROR: Unable to resolve dependency for ':SharedCode#debug/compileClasspath': Could not resolve com.squareup.sqldelight:runtime:1.1.3.
ERROR: Unable to resolve dependency for ':SharedCode#debug/compileClasspath': Could not resolve com.squareup.sqldelight:runtime-jvm:1.1.3.
ERROR: Unable to resolve dependency for ':SharedCode#release/compileClasspath': Could not resolve com.squareup.sqldelight:runtime:1.1.3.
ERROR: Unable to resolve dependency for ':SharedCode#release/compileClasspath': Could not resolve com.squareup.sqldelight:runtime-jvm:1.1.3.**
Gradle version 5.1.1
Gradle Plugin 3.4.0
sqldelight 1.1.3
enableFeaturePreview('GRADLE_METADATA') is present in my settings.gradle
My project gradle file looks like this:
buildscript {
ext {
kotlin_version = '1.3.31'
ktor_version = '1.2.1'
ktor_json_version = '1.2.1'
kotlinx_coroutines_version = '1.2.1'
serialization_version = '0.11.0'
sqldelight_version = '1.1.3'
dokka_version = '0.9.16'
}
repositories {
google()
jcenter()
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
classpath "com.squareup.sqldelight:gradle-plugin:$sqldelight_version"
}
}
allprojects {
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
}
task clean(type: Delete) {
setDelete rootProject.buildDir
}
my SharedCode lib gradle file:
apply plugin: 'kotlinx-serialization'
apply plugin: 'com.android.library'
apply plugin: 'org.jetbrains.kotlin.multiplatform'
apply plugin: 'com.squareup.sqldelight'
group = 'com.example.multiplatform'
version = '1.0'
android {
compileSdkVersion 27
defaultConfig {
minSdkVersion 15
}
buildTypes {
release {
minifyEnabled false
}
}
}
dependencies {
// Specify Kotlin/JVM stdlib dependency.
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7'
implementation "com.squareup.sqldelight:runtime:1.1.3"
testImplementation 'junit:junit:4.12'
testImplementation 'org.jetbrains.kotlin:kotlin-test'
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
androidTestImplementation 'junit:junit:4.12'
androidTestImplementation 'org.jetbrains.kotlin:kotlin-test'
androidTestImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
kotlin {
targets {
final def iOSTarget = System.getenv('SDK_NAME')?.startsWith("iphoneos") \
? presets.iosArm64 : presets.iosX64
fromPreset(iOSTarget, 'ios') {
binaries {
framework('SharedCode')
}
}
fromPreset(presets.android, 'androidLib')
}
sourceSets {
commonMain {
dependencies {
//HTTP
implementation "io.ktor:ktor-client-json:$ktor_json_version"
implementation "io.ktor:ktor-client-serialization:$ktor_version"
//Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$kotlinx_coroutines_version"
//Kotlinx serialization
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
//sqldelight
implementation "com.squareup.sqldelight:runtime:$sqldelight_version"
}
}
androidLibMain {
dependencies {
//HTTP
implementation "io.ktor:ktor-client-json-jvm:$ktor_json_version"
implementation "io.ktor:ktor-client-serialization-jvm:$ktor_version"
//Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinx_coroutines_version"
//Kotlinx serialization
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
//sqldelight
implementation "com.squareup.sqldelight:android-driver:$sqldelight_version"
}
}
iosMain {
dependencies {
//HTTP
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-json-native:$ktor_json_version"
implementation "io.ktor:ktor-client-serialization-native:$ktor_version"
//Coroutines
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$kotlinx_coroutines_version"
//kotlinx serialization
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
//sqldelight
implementation "com.squareup.sqldelight:ios-driver:$sqldelight_version"
}
}
}
}
sqldelight {
MyApp {
packageName = 'com.example.multiplatform'
}
}
configurations {
compileClasspath
}
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
final def framework = kotlin.targets.ios.binaries.getFramework("SharedCode", mode)
inputs.property "mode", mode
dependsOn framework.linkTask
from { framework.outputFile.parentFile }
into frameworkDir
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$#\n"
setExecutable(true)
}
}
}
tasks.build.dependsOn packForXCode
I was solved this problem.
First: Apply sqldelight plugin right to all project:
apply plugin: 'com.squareup.sqldelight'
sqldelight {
MyDatabase {
packageName = "ru.trendagent.database"
sourceFolders = ["sqldelight"]
}
}
In android section add:
packagingOptions {
...
exclude 'META-INF/*.kotlin_module'
}
remove all implementations of sqldelight from CommonMain section
add implementation to AndroidMain section:
implementation "com.squareup.sqldelight:android-driver:1.1.3" //DataBase
add implementation to iosMain section if need:
implementation "com.squareup.sqldelight:ios-driver:1.1.3"//DataBase
add Metadata settings to gradle to settings.gradle file:
enableFeaturePreview("GRADLE_METADATA") // IMPORTANT!
Fully clean gradle files, reset gradle wrapper and other.
Don't use kotlin 1.4.0. It unsupport sqldelight 1.1.3 version
Change gradle to latest version. You can download latest gradle manually and set it on IDE. You need gradle 5.3.1 or latest (5.1.1 unsupported)
If error will remain - change IDE to intellij idea comunity edition
This is seems to me as an error occurred due to offline gradle or invalid cache as this error is not specific to com.squareup.sqldelight. To resolve this issue follow the following steps:
File
Settings
Build, Execution, Deployment
Gradle
Uncheck offline work
and then try to invalidate the cache and restart from file menu. Hope it helps!
Change this
classpath "com.squareup.sqldelight:gradle-plugin:$sqldelight_version"
Following
classpath "com.squareup.sqldelight:runtime:$sqldelight_version"
you are passing wrong metadata to sqldelight change with my solution it will work
The Gradle part of the readme of the library indicates, that gradle plugin is needed. There's no such sqldelight library as runtime. They only have android-driver, ios-driver and sqlite-driver.
Using the DroidConKotlin app project as an example, I upgraded gradle from 5.1.1 to 5.3.1 and it resolved all the dependencies issues.
You likely are trying to use a dependency on dependant libraries or even applications and not only in commonMain module. Just change:
commonMain {
dependencies {
...
implementation "com.squareup.sqldelight:runtime:$sqldelight_version"
}
}
to
commonMain {
dependencies {
...
api "com.squareup.sqldelight:runtime:$sqldelight_version"
}
}
Also change it on dependencies section
And do the same with any other dependency uncorrecly resolved
This can happen for example if you define a class that implements an interface provided by the dependency and you use or extend that class on dependant libraries or applications (Just an example of millions that could be).
If this is your case, for further understanding, just take a look to this answer:
I have a kotlin-multiplatform project targeting iOS and Android.
Ktor http client is used in common module.
Everything works great with Android app.
But when building project with iOS lib, I receive following exceptions:
> Task :app:compileKotlinIos FAILED
src/commonMain/kotlin/com/ottamotta/mozoli/api/MozoliApiKtor.kt:4:8: error: unresolved reference: io
import io.ktor.client.HttpClient
^
src/commonMain/kotlin/com/ottamotta/mozoli/api/MozoliApiKtor.kt:5:8: error: unresolved reference: io
import io.ktor.client.features.feature
...and other ones, saying none of the ktor dependencies have been resolved.
Here is build.gradle:
plugins {
id 'kotlin-multiplatform' version '1.3.10'
}
repositories {
google()
jcenter()
mavenCentral()
maven { url "https://kotlin.bintray.com/kotlinx" }
}
ext {
support_lib_version = '28.0.0'
ktor_version = '1.0.0'
}
def keystorePropertiesFile = rootProject.file("./app/secret.properties");
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "com.ottamotta.mozoli"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [auth0Domain: "#string/com_auth0_domain", auth0Scheme: "https"]
}
buildTypes {
debug {
resValue "string", "com_auth0_client_id", keystoreProperties['com_auth0_client_id']
}
release {
resValue "string", "com_auth0_client_id", keystoreProperties['com_auth0_client_id']
minifyEnabled false
}
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "com.android.support:recyclerview-v7:${support_lib_version}"
implementation "com.android.support:appcompat-v7:${support_lib_version}"
implementation 'com.squareup.picasso:picasso:2.71828'
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.9.7"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1")
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
implementation "com.auth0.android:auth0:1.14.1"
androidTestImplementation 'com.android.support.test:runner:1.0.2'
}
kotlin {
targets {
fromPreset(presets.android, 'android')
// This preset is for iPhone emulator
// Switch here to presets.iosArm64 (or iosArm32) to build library for iPhone device
fromPreset(presets.iosX64, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
}
}
sourceSets {
commonMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
implementation "io.ktor:ktor-client:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
implementation "io.ktor:ktor-client-jackson:$ktor_version"
}
}
commonTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test-common'
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
}
}
androidMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
implementation "io.ktor:ktor-client-android:$ktor_version"
}
}
androidTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test'
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
}
}
iosMain {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktor_version")
}
}
iosTest {
}
}
}
task copyFramework {
def buildType = project.findProperty("kotlin.build.type") ?: "DEBUG"
def target = project.findProperty("kotlin.target") ?: "ios"
dependsOn "link${buildType.toLowerCase().capitalize()}Framework${target.capitalize()}"
doLast {
def srcFile = kotlin.targets."$target".compilations.main.getBinary("FRAMEWORK", buildType)
def targetDir = getProperty("configuration.build.dir")
copy {
from srcFile.parent
into targetDir
include 'app.framework/**'
include 'app.framework.dSYM'
}
}
}
Here is the code of the file from common module which generates errors:
package com.ottamotta.mozoli.api
import com.ottamotta.mozoli.*
import io.ktor.client.HttpClient
import io.ktor.client.features.feature
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.JsonSerializer
import io.ktor.client.features.json.defaultSerializer
import io.ktor.client.request.header
import io.ktor.client.request.request
import io.ktor.client.request.url
import io.ktor.http.HttpMethod
class MozoliApiKtor(
private val serverUrl: String,
private var jsonSerializer: JsonSerializer? = null,
private val tokenProvider: suspend () -> String?
) : MozoliApi {
private val client: HttpClient
private val AUTH_HEADER = "Authorization";
private val TOKEN_PREFIX = "Bearer "
init {
client = HttpClient {
install(JsonFeature) {
serializer = jsonSerializer ?: defaultSerializer()
}
}
jsonSerializer = client.feature(JsonFeature)?.serializer
}
override suspend fun getUserProfile(): User {
return client.request {
url("${serverUrl}/user/")
method = HttpMethod.Get
header(AUTH_HEADER, TOKEN_PREFIX + tokenProvider())
}
}
override suspend infix fun getEventsByCity(cityId: String): List<Event> {
return client.request {
url("${serverUrl}/event/city/${cityId}")
method = HttpMethod.Get
header(AUTH_HEADER, TOKEN_PREFIX + tokenProvider())
}
}
}
I was having the same exact issue as you. Built and works flawlessly for the Android app, but the iOS module cannot find any Ktor, coroutine, or kotlinx serialization class.
Following along https://github.com/adrianbukros/github-multiplatform-example, and trying to copy their set up, I finally got the packForXCode task to work by copying some of their gradle set up namely:
Their common module build.gradle, which should look like this:
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'
kotlin {
targets {
fromPreset(presets.jvm, "android")
fromPreset(presets.iosX64, "ios_x86_64")
fromPreset(presets.iosArm64, "ios_arm64")
configure([ios_x86_64, ios_arm64]) {
compilations.main.outputKinds("FRAMEWORK")
}
}
sourceSets {
commonMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
}
androidMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
}
iosMain.dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-core-ios:$ktor_version"
implementation "io.ktor:ktor-client-json-ios:$ktor_version"
}
configure([ios_x86_64Main, ios_arm64Main]) {
dependsOn iosMain
}
}
}
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String configuration = project.findProperty("CONFIGURATION")?.toUpperCase() ?: "DEBUG"
final String arch = project.findProperty("ARCHS") ?: "x86_64"
dependsOn kotlin.targets."ios_${arch}".compilations.main.linkTaskName("FRAMEWORK", configuration)
from { kotlin.targets."ios_${arch}".compilations.main.getBinary("FRAMEWORK", configuration).parentFile }
into frameworkDir
}
tasks.build.dependsOn packForXCode
And their settings.gradle file which should look like this:
enableFeaturePreview("GRADLE_METADATA") // IMPORTANT!
include 'commoncode'
include 'app'
If it's still not working, look at all of their *.gradle and gradle.* files and see how yours are different.
That finally allowed the task to pass for me, and I can use my Kotlin Ktor code in XCode. However, now Android Studio is saying "Kotlin is not configured" for the shared iOS module. I will report back if I figure out why, and if you find something, please share!
EDIT
Changed the common module build.gradle to look like this, seems like everything is working well!
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlinx-serialization'
kotlin {
targets {
fromPreset(presets.jvm, 'android')
// Change to `presets.iosArm64` to deploy the app to iPhone
fromPreset(presets.iosX64, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
}
}
sourceSets {
commonMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-json:$ktor_version"
}
androidMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
implementation "io.ktor:ktor-client-core-jvm:$ktor_version"
implementation "io.ktor:ktor-client-json-jvm:$ktor_version"
}
iosMain.dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
implementation "io.ktor:ktor-client-ios:$ktor_version"
implementation "io.ktor:ktor-client-core-ios:$ktor_version"
implementation "io.ktor:ktor-client-json-ios:$ktor_version"
}
}
}
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
task packForXCode(type: Sync) {
final File frameworkDir = new File(buildDir, "xcode-frameworks")
final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
inputs.property "mode", mode
dependsOn kotlin.targets.ios.compilations.main.linkTaskName("FRAMEWORK", mode)
from { kotlin.targets.ios.compilations.main.getBinary("FRAMEWORK", mode).parentFile }
into frameworkDir
doLast {
new File(frameworkDir, 'gradlew').with {
text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$#\n"
setExecutable(true)
}
}
}
tasks.build.dependsOn packForXCode
As of now kotlin multiplatform for iOS does not run on windows. This would explain why only the dependencies in your iosmain code wont resolve.