You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio集成OpenAI API遇Ktor ContentNegotiation类找不到崩溃问题

集成OpenAI API时Android应用启动崩溃(找不到ContentNegotiation类)

问题背景

正在开发一款文本RPG Android应用,使用Kotlin语言。UI完成后开始集成OpenAI API,编写了API请求代码,IDE中无语法错误,但应用启动时立即崩溃。

崩溃日志

启动时Logcat输出如下错误:

java.lang.NoClassDefFoundError: Failed resolution of: Lio/ktor/client/plugins/contentnegotiation/ContentNegotiation;

...

Caused by: java.lang.ClassNotFoundException: Didn't find class "io.ktor.client.plugins.contentnegotiation.ContentNegotiation" on path: DexPathList[[zip file "/data/app/~~PDlu8hz4gyE6dIA4WjsxSA==/com.example.worldcrafter-jSXV8Rrpgh6Ga_DxfOZ7qg==/base.apk"],nativeLibraryDirectories=[/data/app/~~PDlu8hz4gyE6dIA4WjsxSA==/com.example.worldcrafter-jSXV8Rrpgh6Ga_DxfOZ7qg==/lib/x86_64, /data/app/~~PDlu8hz4gyE6dIA4WjsxSA==/com.example.worldcrafter-jSXV8Rrpgh6Ga_DxfOZ7qg==/base.apk!/lib/x86_64, /system/lib64, /system_ext/lib64]]

应用启动前还有两条警告:

com.example.worldcrafter             W  Unable to open '/data/app/~~PDlu8hz4gyE6dIA4WjsxSA==/com.example.worldcrafter-jSXV8Rrpgh6Ga_DxfOZ7qg==/base.dm': No such file or directory
2024-12-12 11:50:03.402 20454-20454 ziparchive
com.example.worldcrafter             W  Unable to open '/data/app/~~PDlu8hz4gyE6dIA4WjsxSA==/com.example.worldcrafter-jSXV8Rrpgh6Ga_DxfOZ7qg==/base.dm': No such file or directory

API请求代码

编写的OpenAI API请求函数如下:

@OptIn(DelicateCoroutinesApi::class)
fun makeAPIRequest(message: String) {
    // Launch a coroutine to handle the API request asynchronously
    GlobalScope.launch(Dispatchers.IO) {
        // Create a ChatCompletionRequest to send to OpenAI
        val chatRequest = ChatCompletionRequest(
            model = ModelId("gpt-3.5-turbo-1106"), // Use the correct model name
            messages = mutableListOf(
                ChatMessage(
                    role = Role.User, // User sends the message
                    content = message  // The message entered by the user
                )
            ),
            temperature = 0.7,
            maxTokens = 150
        )

        // Send the request to OpenAI API and get the response asynchronously
        val response = openAI.chatCompletion(chatRequest)

        // Process the response on the main thread
        withContext(Dispatchers.Main) {
            val responseMessage = response.choices.first().message
            // Handle the response here, e.g., update UI or process data
            chatGPTResponse = responseMessage.toString()
        }
    }
}

注:未将该函数设为async是因为要在MainActivity.kt的其他地方调用。

依赖配置

当前项目的依赖配置如下:

dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.lifecycle.runtime.ktx)
    implementation(libs.androidx.activity.compose)
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.ui)
    implementation(libs.androidx.ui.graphics)
    implementation(libs.androidx.ui.tooling.preview)
    implementation(libs.androidx.material3)
    implementation(libs.androidx.constraintlayout)
    implementation(libs.androidx.recyclerview)
    implementation(libs.material)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
    androidTestImplementation(platform(libs.androidx.compose.bom))
    androidTestImplementation(libs.androidx.ui.test.junit4)
    debugImplementation(libs.androidx.ui.tooling)
    debugImplementation(libs.androidx.ui.test.manifest)
    implementation("com.aallam.openai:openai-client:3.8.2")
    implementation(platform(libs.ktor.bom))
    //not using the toml file because i hate it with a burning passion
    implementation("io.ktor:ktor-client-core:3.0.2")
    implementation("io.ktor:ktor-client-android:3.0.2")
    implementation("io.ktor:ktor-client-content-negotiation:3.0.2")
    implementation("io.ktor:ktor-serialization-kotlinx-json:3.0.2")
    implementation("io.ktor:ktor-client-logging:3.0.2")
    implementation("io.ktor:ktor-client-cio:3.0.2")
}

MainActivity精简代码

package com.example.worldcrafter

import android.os.Bundle
import android.view.KeyEvent
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.aallam.openai.api.chat.*
import com.aallam.openai.api.model.ModelId
import com.aallam.openai.api.core.Role
import com.aallam.openai.api.http.Timeout
import com.aallam.openai.client.OpenAI
import com.aallam.openai.client.OpenAIConfig
import com.example.worldcrafter.ui.adapters.ChatAdapter
import com.google.android.material.textfield.TextInputEditText
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlin.time.Duration.Companion.seconds

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

// App startup
class MainActivity() : ComponentActivity() {

    val openAI = OpenAI(OpenAIConfig(BuildConfig.OPENAI_API_KEY, timeout = Timeout(socket = 60.seconds)))

    var chatGPTResponse: String = ""

    // on creation of app
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 省略其他初始化代码,调用initChatButtons()
    }

    // Initialize the buttons in the Chat layout
    private fun initChatButtons() {
        // Setup navigation buttons
        setupButton(R.id.btSavedChats2) { switchLayout(LayoutType.SAVED_CHATS) }
        setupButton(R.id.btSettings2) { switchLayout(LayoutType.SETTINGS) }

        // Initialize mutable list to store messages
        val messages = mutableListOf<String>()

        // Set up RecyclerView and Adapter
        val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
        val chatAdapter = ChatAdapter(messages) // Use ChatAdapter directly
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = chatAdapter

        // Reference to TextInputEditText
        val inputEditText = findViewById<TextInputEditText>(R.id.textInputEditText)

        // Set an action listener to detect "Enter" key
        inputEditText.setOnEditorActionListener { _, actionId, event ->
            if (actionId == EditorInfo.IME_ACTION_DONE || (event != null && event.keyCode == KeyEvent.KEYCODE_ENTER)) {
                val message = inputEditText.text.toString().trim()

                if (message.isNotEmpty()) {
                    // Use addMessage() instead of direct list manipulation
                    chatAdapter.addMessage(message)

                    // Scroll to the latest message
                    recyclerView.smoothScrollToPosition(messages.size - 1)

                    //chatgpt message here
                    makeAPIRequest(message)

                    // Add the response to the list
                    chatAdapter.addMessage(chatGPTResponse)

                    recyclerView.smoothScrollToPosition(messages.size - 1)

                    // Clear the input field
                    inputEditText.text?.clear()

                    // Hide the keyboard after the message is added
                    hideKeyboard()

                    return@setOnEditorActionListener true
                }
            }
            false
        }
    }

    //chatgpt stuff
    @OptIn(DelicateCoroutinesApi::class)
    fun makeAPIRequest(message: String) {
        // Launch a coroutine to handle the API request asynchronously
        GlobalScope.launch(Dispatchers.IO) {
            // Create a ChatCompletionRequest to send to OpenAI
            val chatRequest = ChatCompletionRequest(
                model = ModelId("gpt-3.5-turbo-1106"), // Use the correct model name
                messages = mutableListOf(
                    ChatMessage(
                        role = Role.User, // User sends the message
                        content = message  // The message entered by the user
                    )
                ),
                temperature = 0.7,
                maxTokens = 150
            )

            // Send the request to OpenAI API and get the response asynchronously
            val response = openAI.chatCompletion(chatRequest)

            // Process the response on the main thread
            withContext(Dispatchers.Main) {
                val responseMessage = response.choices.first().message
                // Handle the response here, e.g., update UI or process data
                chatGPTResponse = responseMessage.toString()
            }
        }
    }
}

已尝试的解决方法

  • 清理并重建项目
  • 更换Content Negotiation、Kotlin及Ktor的版本

以上方法均未解决问题,寻求帮助。


内容的提问来源于stack exchange,提问作者Alexander Mailyants

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:05:02