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

Android Volley发起POST请求返回400错误,求排查问题

问题排查与修复方案

核心问题点分析

1. Content-Type请求头冲突

你在getHeaders()里设置了Content-Type: application/x-www-form-urlencoded; charset=utf-8,但同时重写getBodyContentType()返回application/json,导致请求头中Content-Type字段混乱。API服务器无法正确识别请求体格式,直接返回400错误。

2. 关键参数未初始化

emp_num变量仅声明为null,未赋值就放入请求JSON中,导致API接收到的exp_number参数为空,不符合接口要求,触发400错误。

3. 冗余代码无意义

代码中创建了jsonObj但未使用,虽不影响功能,但增加了代码冗余。

修复步骤

  1. 统一Content-Type请求头
    移除getHeaders()中的Content-Type设置,JsonObjectRequest会通过getBodyContentType()自动设置正确的JSON格式请求头,无需手动添加。

  2. 初始化emp_num参数
    在调用submitdata()前,给emp_num赋值为有效的员工编号(比如从SharedPreferences或Intent中获取)。

  3. 清理冗余代码
    删除未使用的jsonObj变量。

修改后的关键代码片段

修复后的submitdata方法

fun submitdata(url: String?) {
    progressBar!!.visibility = View.VISIBLE
    // 确保emp_num已被正确赋值,替换为实际获取逻辑
    emp_num = SharedPrefrence.getEmpNumber(applicationContext)
    val js = JSONObject()
    try {
        js.put("year", financialyear!!.selectedItem.toString())
        js.put("month", month!!.selectedItem.toString())
        js.put("exp_number", emp_num)
    } catch (e: JSONException) {
        e.printStackTrace()
    }
    val JsonObjectRequest = object : JsonObjectRequest(
        Request.Method.POST, url, js,
        Response.Listener { response ->
            val pdfUrl = response.getString("pdfUrl")
            fetchPdf(applicationContext, pdfUrl)
            Toast.makeText(this@PayslipActivity, response.toString(), Toast.LENGTH_LONG).show()
            progressBar!!.visibility = View.GONE
        },
        Response.ErrorListener { error ->
            Log.e("Volley", "Error: $error")
            Toast.makeText(this@PayslipActivity, "请求失败:${error.message}", Toast.LENGTH_LONG).show()
            progressBar!!.visibility = View.GONE
            if (error is VolleyError && error.networkResponse != null) {
                val statusCode = error.networkResponse.statusCode
                if (statusCode == 400) {
                    Log.e("Volley", "Bad Request: ${error.message}")
                    Toast.makeText(this@PayslipActivity, "参数错误,请检查输入", Toast.LENGTH_LONG).show()
                }
            }
        }) {

        @Throws(AuthFailureError::class)
        override fun getHeaders(): Map<String, String> {
            val headers = HashMap<String, String>()
            headers["Authorization"] = "Bearer " + SharedPrefrence.getApitoken(applicationContext)
            headers["x-api-key"] = SharedPrefrence.getApikey(applicationContext)!!
            // 移除冲突的Content-Type设置
            return headers
        }

        override fun getBodyContentType(): String {
            return "application/json; charset=utf-8" // 明确指定编码
        }
    }
    JsonObjectRequest.retryPolicy = DefaultRetryPolicy(
        100000,
        DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
    )
    val requestQueue = Volley.newRequestQueue(this)
    requestQueue.add(JsonObjectRequest)
}

补充emp_num初始化逻辑

在onCreate()中添加emp_num的赋值逻辑:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_payslip)
    // ... 其他初始化代码
    // 初始化员工编号,替换为实际获取方式
    emp_num = SharedPrefrence.getEmpNumber(applicationContext)
}

额外建议

  • 开启Volley日志调试,对比实际发送的请求头、请求体与Postman的内容,确认是否一致。
  • 检查SharedPreferences中存储的token和api-key是否与Postman中使用的完全一致,避免字符截断或空格导致的认证失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 21:57:03