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

Kotlin使用Fuel发送POST请求时服务器无响应问题排查求助

问题

我在使用Fuel库向服务器发送POST请求时遇到异常:本次请求的特殊配置为通过Bearer Token完成授权,且请求内容类型为JSON,相关实现代码如下:

fun callApi(site:String, token: String):String {

  val(request, response, result) = Fuel.post(site)
    .authentication()
    .bearer(token)
    .jsonBody("{\"instrumentStatus\":\"INSTRUMENT_STATUS_UNSPECIFIED\"}")
    .responseString()

return response.toString()   
}

我编写了一个接收请求路径、已知Bearer Token作为入参的函数,随后在MainActivity.kt中定义site、token两个变量,调用callApi函数并将返回数据传递给TextView进行展示,相关代码如下:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val token = "t.GtiJaNIjpWy-Iw4sFSFvIEQHdCxxQS7Nz1HHTP4tM3pmfrXPyP3LbqJnbJln2Lpv85BiMK-ry3ynhzFFVgJM_A"
    val site = "https://invest-public-api.tinkoff.ru/rest/tinkoff.public.invest.api.contract.v1.InstrumentsService/Bonds"

    val textView: TextView = findViewById(R.id.textView)

     textView.text = callApi(site,token)
}
}

我已通过Postman验证服务器接口可用性,Postman中配置完全相同的请求参数时可正常收到响应,不清楚代码为何无法拿到返回数据。

错误原因

你的代码存在3个直接导致请求失败/拿不到正确结果的问题:

  • 主线程发起网络请求。Android API 11及以上版本默认禁止在UI主线程执行网络操作,你在onCreate生命周期里直接调用同步阻塞的responseString()方法,会直接抛出NetworkOnMainThreadException,请求根本没有发出去。Postman作为桌面端程序没有Android的线程限制,所以可以正常请求。
  • 缺少网络权限声明。Android应用发起网络请求必须在AndroidManifest.xml中声明INTERNET权限,没有该权限所有网络操作都会被系统直接拦截。
  • 返回值处理逻辑完全错误。首先response.toString()返回的是Response类实例的对象字符串(格式类似com.github.kittinunf.fuel.core.Response@1a2b3c),根本不是接口返回的响应体内容;其次你完全没处理result中封装的请求异常,所有报错都被吞掉,无法定位问题。另外多余调用了.authentication()方法,这个方法是给Basic基础认证(用户名密码认证)用的,Bearer Token认证不需要调用,多余调用可能干扰请求头生成。
修复步骤
  1. 首先在AndroidManifest.xml的<manifest>节点下(与<application>节点平级)添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
  1. 改造callApi方法,使用Fuel的异步请求方式,移除多余的authentication调用,正确处理响应结果和异常,注意异步请求不能直接返回值,需要通过回调回传结果:
fun callApi(site: String, token: String, callback: (resultText: String) -> Unit) {
    Fuel.post(site)
        .bearer(token)
        .jsonBody("{\"instrumentStatus\":\"INSTRUMENT_STATUS_UNSPECIFIED\"}")
        .responseString { _, _, result ->
            when (result) {
                is Result.Success -> {
                    // 从result中取真正的响应体内容
                    val responseContent = result.get()
                    // 切回主线程更新UI
                    Handler(Looper.getMainLooper()).post {
                        callback(responseContent)
                    }
                }
                is Result.Failure -> {
                    val error = result.getException()
                    error.printStackTrace()
                    Handler(Looper.getMainLooper()).post {
                        callback("请求出错:${error.message}")
                    }
                }
            }
        }
}
  1. 修改Activity中的调用逻辑,通过回调接收结果更新TextView:
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val token = "t.GtiJaNIjpWy-Iw4sFSFvIEQHdCxxQS7Nz1HHTP4tM3pmfrXPyP3LbqJnbJln2Lpv85BiMK-ry3ynhzFFVgJM_A"
        val site = "https://invest-public-api.tinkoff.ru/rest/tinkoff.public.invest.api.contract.v1.InstrumentsService/Bonds"
        val textView: TextView = findViewById(R.id.textView)

        callApi(site, token) { result ->
            textView.text = result
        }
    }
}

补充:你调用的接口是HTTPS协议,不需要额外配置明文流量权限,改完以上三点即可正常拿到响应。


内容的提问来源于stack exchange,提问作者Vladislav Ponomaryov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:42:17