【问题标题】:Volley POST Request with headers and raw json body带有标头和原始 json 正文的 Volley POST 请求
【发布时间】:2020-01-02 01:28:42
【问题描述】:

我正在尝试从 Android 应用发出 Post 请求,该请求在请求正文中使用用户名和密码,并在标头中使用内容类型 application/json。

我尝试更改内容类型以及如何在正文中发送用户名密码,但仍然没有运气

public class MainActivity extends AppCompatActivity {

    private Button Login;
    private EditText loginEmail, loginPassword;

    String URL = "https://localhost:8080/api/v1/auth";


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        loginEmail = (EditText)findViewById(R.id.etUsername);
        loginPassword = (EditText)findViewById(R.id.etPassword);
        Login = (Button)findViewById(R.id.btnLogin);

        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("username", loginEmail.getText().toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        try {
            jsonObject.put("password", loginPassword.getText().toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }

        final String requestBody = jsonObject.toString();


        Login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                StringRequest request = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Toast.makeText(MainActivity.this, response, Toast.LENGTH_LONG).show();
                        startActivity(new Intent(MainActivity.this, LandingPage.class));
                        finish();
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_LONG).show();
                        NetworkResponse response = error.networkResponse;
                        if (error instanceof ServerError && response != null) {
                            try {
                                String res = new String(response.data,
                                        HttpHeaderParser.parseCharset(response.headers, "utf-8"));
                                // Now you can use any deserializer to make sense of data
                                JSONObject obj = new JSONObject(res);
                                Toast.makeText(MainActivity.this, res, Toast.LENGTH_LONG).show();
                                Log.i("MainActivity", res);
                                //use this json as you want
                            } catch (UnsupportedEncodingException e1) {
                                // Couldn't properly decode data to string
                                e1.printStackTrace();
                            } catch (JSONException e2) {
                                // returned data is not JSONObject?
                                e2.printStackTrace();
                            }
                        }
                    }
                })

                {
                    @Override
                    public String getBodyContentType() {
                        return "application/json; charset=utf-8";
                    }

                    @Override
                    public byte[] getBody() throws AuthFailureError {
                        try {
                            return requestBody == null ? null : requestBody.getBytes("utf-8");
                        } catch (UnsupportedEncodingException uee) {
                            VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
                            return null;
                        }
                    }

                    @Override
                    public Map<String, String> getHeaders() throws AuthFailureError {
                        Map<String, String> params = new HashMap<String, String>();
                            params.put("Content-Type", "application/json");

                        return params;
                    }

                };
                RequestQueue rQueue = Volley.newRequestQueue(MainActivity.this);
                rQueue.add(request);
            }
        });
    }
}


来自 Postman 的 Post Request 工作得非常好,但 Volley 会引发错误 400。 以下是我在控制台中遇到的错误 "errorSummary":"错误请求。Accept 和/或 Content-Type 标头可能与支持的值不匹配。"

【问题讨论】:

  • 您可以尝试使用自定义请求并扩展Request&lt;JSONObject&gt;,而不是使用StringRequest。就我而言,它是这样工作的。
  • @MaximilianSpeicher 你能提供一个示例代码吗?我对 android 很陌生
  • 请稍等。

标签: android authentication post android-volley postman


【解决方案1】:

尝试使用自定义请求并扩展Request&lt;JSONObject&gt;

CustomRequest类:

public class CustomRequest extends Request<JSONObject> {
    private final Map<String, String> mHeaders;
    private final JSONObject mBody;
    private final Response.Listener<JSONObject> mResponseListener;

    public CustomRequest(int method, String url, Map<String, String> headers, JSONObject body, Response.Listener<JSONObject> responseListener, Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mHeaders = headers;
        this.mBody = body;
        this.mResponseListener = responseListener;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return mHeaders != null ? mHeaders : super.getHeaders();
    }

    @Override
    public String getBodyContentType() {
        return "application/json; charset=UTF-8";
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        return mBody != null ? mBody.toString().getBytes(Charset.forName("UTF-8")) : super.getBody();
    }

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException | JSONException e) {
            return Response.error(new ParseError(e));
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        mResponseListener.onResponse(response);
    }
}

用法:

String url = "https://localhost:8080/api/v1/auth";


Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");

JSONObject jsonObject = new JSONObject();
try {
    jsonObject.put("username", loginEmail.getText().toString());
    jsonObject.put("password", loginPassword.getText().toString());
} catch (JSONException e) {
        e.printStackTrace();
}

CustomRequest customRequest = new CustomRequest(Request.Method.POST, url, headers, jsonObject, response -> {
    // put your reponse listener code here
}, error -> {
    // put your error listener code here
});

RequestQueue queue = Volley.newRequestQueue(context);
queue.add(customRequest);

【讨论】:

  • 我仍然收到错误 400。请查看有问题的 Postman 屏幕截图,看看是否可以找到需要更改的内容。
  • @JanakSoni 我忘了添加parseNetworkResponse 函数。您可以检查编辑并检查它现在是否有效。如果它不起作用,您是否检查过您是否从 EditText 获得了正确的用户名和密码,如果您使用的是 localhost,您的测试设备是否可以使用 API url?
  • 我在 CustomRequest 中添加了 parseNetworkResponse。是的,我正在记录用户名和密码。它们是正确的。
  • 您是刚刚添加了parseNetworkResponse 还是按照我编辑的方式实现了?
  • 首先我刚刚生成了一个空的,现在我添加了你实现的方式。
猜你喜欢
  • 2019-12-13
  • 1970-01-01
  • 2021-08-11
  • 2017-08-31
  • 2015-12-02
  • 2016-09-24
  • 2020-12-23
  • 1970-01-01
  • 2021-05-24
相关资源
最近更新 更多