我有一个针对iOS和Android的kotlin跨平台项目。 通用模块中使用了Ktor http客户端。
一切都适用于Android应用。 但是当使用iOS lib构建项目时,我收到以下异常:
> 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
...和其他,说没有ktor依赖关系已解决。
这是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'
}
}
}
这是来自公共模块的文件代码,会产生错误:
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())
}
}
}
答案 0 :(得分:5)
我和您有同样的问题。可为Android应用程序完美构建和运行,但iOS模块找不到任何Ktor,协程或kotlinx序列化类。
跟随https://github.com/adrianbukros/github-multiplatform-example,并尝试复制他们的设置,我终于通过复制他们的一些gradle设置来完成packForXCode
的工作:
它们的通用模块build.gradle
,应如下所示:
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
其settings.gradle
文件应如下所示:
enableFeaturePreview("GRADLE_METADATA") // IMPORTANT!
include 'commoncode'
include 'app'
如果仍然无法正常工作,请查看它们的所有*.gradle
和gradle.*
文件,看看它们的不同之处。
这最终使任务得以通过,我可以在XCode中使用我的Kotlin Ktor代码。但是,现在Android Studio对共享的iOS模块说“未配置Kotlin”。如果我找出原因,我会报告,如果您发现有什么问题,请分享!
编辑
更改了通用模块build.gradle
如下所示,似乎一切正常!
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
答案 1 :(得分:0)
到目前为止,iOS的kotlin跨平台无法在Windows上运行。这可以解释为什么只有iosmain代码中的依赖项无法解决。