You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android Studio Kotlin调用Wolfram Alpha API点击按钮崩溃返回主页面

解决你的Wolfram Alpha API调用崩溃问题

嘿,看了你的代码和错误日志,我发现两个核心问题导致点击按钮后Activity崩溃返回主页面:

问题1:khttp库在Android上的兼容性问题

你用的khttp库并不是为Android平台设计的,它内部通过反射访问java.net.URLhost字段,但Android的URL类实现里并没有这个可被反射访问的字段,这直接触发了NoSuchFieldException,导致App崩溃。

问题2:主线程发起网络请求

你直接在按钮的点击回调里调用khttp.get(),这是在Android的主线程执行网络操作——而Android从API 11开始就严格禁止主线程做网络请求,这也会抛出异常,让Activity被迫关闭。

下面是具体的修复方案:

第一步:替换成Android兼容的网络库(用OkHttp)

放弃khttp,改用官方推荐的OkHttp,它对Android的兼容性很好。先在模块级的build.gradle里添加依赖:

dependencies {
    // 保留你原有的依赖,加上这一行
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
}

第二步:修改CalcActivity代码,正确发起异步请求

同时还要注意,你之前用的是Wolfram Alpha的网页地址,不是官方API接口!得换成正确的API端点,并且用异步请求避免阻塞主线程:

package com.example.prac
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_calc.*
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.IOException

class CalcActivity : AppCompatActivity() {
    // 替换成Wolfram Alpha的官方API地址
    private val BASE_API_URL = "https://api.wolframalpha.com/v2/query"
    private val APP_ID = "你的真实APP_ID" // 替换成你的开发者ID
    private val okHttpClient = OkHttpClient()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_calc)
        val transferBtn = findViewById<Button>(R.id.transfer)

        transferBtn.setOnClickListener {
            val inputText = poly_edit.text.toString().trim()
            if (inputText.isEmpty()) {
                grabwolf.text = "请输入内容"
                return@setOnClickListener
            }

            // 处理输入文本,适配API的查询格式
            val encodedQuery = inputText.replace("+", " plus ").replace(" ", "+")
            // 构建正确的API请求URL,指定返回纯文本格式
            val requestUrl = "$BASE_API_URL?input=$encodedQuery&appid=$APP_ID&format=plaintext"

            val request = Request.Builder()
                .url(requestUrl)
                .build()

            // 异步发起网络请求,不会阻塞主线程
            okHttpClient.newCall(request).enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    // 请求失败时,回到主线程更新UI
                    runOnUiThread {
                        grabwolf.text = "请求出错:${e.message}"
                    }
                }

                override fun onResponse(call: Call, response: Response) {
                    response.use {
                        val responseContent = if (response.isSuccessful) {
                            response.body?.string() ?: "无返回数据"
                        } else {
                            "请求失败,状态码:${response.code}"
                        }
                        // 必须在主线程更新UI组件
                        runOnUiThread {
                            grabwolf.text = responseContent
                        }
                    }
                }
            })
        }
    }
}

第三步:确认网络权限

检查你的AndroidManifest.xml里有没有添加网络权限,没有的话加上:

<uses-permission android:name="android.permission.INTERNET" />

额外提示

  • 一定要用Wolfram Alpha的官方API端点(v2/query),而不是网页地址,否则你拿到的是网页HTML,不是结构化的API数据。
  • 所有UI更新操作必须在主线程执行,所以我们用runOnUiThread来切换线程。

内容的提问来源于stack exchange,提问作者Jeffrey Jordan

火山引擎 最新活动