在 Android 中使用带有 post 参数的 HttpClient 和 HttpPost

Posted

技术标签:

【中文标题】在 Android 中使用带有 post 参数的 HttpClient 和 HttpPost【英文标题】:Using HttpClient and HttpPost in Android with post parameters 【发布时间】:2011-05-17 09:39:20 【问题描述】:

我正在为一个 android 应用程序编写代码,该应用程序应该获取数据,将其打包为 Json 并将其发布到 Web 服务器,而 Web 服务器又应该使用 json 响应。

使用 GET 请求可以正常工作,但由于某种原因,使用 POST 似乎所有数据都被剥离并且服务器没有收到任何内容。

这是代码的sn-p:

HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 5000);        
DefaultHttpClient httpClient = new DefaultHttpClient(params);
BasicCookieStore cookieStore = new BasicCookieStore();
httpClient.setCookieStore(cookieStore);

String uri = JSON_ADDRESS;
String result = "";
String username = "user";
String apikey = "something";
String contentType = "application/json";

JSONObject jsonObj = new JSONObject();

try 
    jsonObj.put("username", username);
    jsonObj.put("apikey", apikey);
 catch (JSONException e) 
    Log.e(TAG, "JSONException: " + e);


HttpPost httpPost = new HttpPost(uri);
List<NameValuePair> postParams = new ArrayList<NameValuePair>();
postParams.add(new BasicNameValuePair("json", jsonObj.toString()));
HttpGet httpGet = null;
try 
    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postParams);
    entity.setContentEncoding(HTTP.UTF_8);
    entity.setContentType("application/json");
    httpPost.setEntity(entity);

    httpPost.setHeader("Content-Type", contentType);
    httpPost.setHeader("Accept", contentType);
 catch (UnsupportedEncodingException e) 
    Log.e(TAG, "UnsupportedEncodingException: " + e);


try 
    HttpResponse httpResponse = httpClient.execute(httpPost);
    HttpEntity httpEntity = httpResponse.getEntity();

    if (httpEntity != null) 
        InputStream is = httpEntity.getContent();
        result = StringUtils.convertStreamToString(is);
        Log.i(TAG, "Result: " + result);
    
 catch (ClientProtocolException e) 
    Log.e(TAG, "ClientProtocolException: " + e);
 catch (IOException e) 
    Log.e(TAG, "IOException: " + e);


return result;

我认为我已遵循有关如何创建参数和发布参数的一般准则,但显然没有。

在这一点上,我非常欢迎任何帮助或指向我可以找到解决方案的指针(在花了几个小时后才意识到从未发送过任何帖子数据)。真正的服务器是在 Tomcat 上运行 Wicket,但我也在一个简单的 php 页面上对其进行了测试,没有任何区别。

【问题讨论】:

用解决方案更新(在这种特殊情况下至少对我有用)我删除了所有设置Content-Type的方法调用和现在它可以工作了。在这种情况下,唯一允许的内容类型方法调用是 httpPost.setHeader("Accept", contentType); 这是因为 UrlEncodedFormEntity 将内容类型设置为 application/x-www-form-urlencoded。如果您将内容类型更改为其他内容(例如 application/json),服务器将无法解析您的请求参数。 【参考方案1】:

您实际上可以通过以下方式将其作为 JSON 发送:

// Build the JSON object to pass parameters
JSONObject jsonObj = new JSONObject();
jsonObj.put("username", username);
jsonObj.put("apikey", apikey);
// Create the POST object and add the parameters
HttpPost httpPost = new HttpPost(url);
StringEntity entity = new StringEntity(jsonObj.toString(), HTTP.UTF_8);
entity.setContentType("application/json");
httpPost.setEntity(entity);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(httpPost);

【讨论】:

谢谢!使用 namevaluepairs 对我不起作用,但这恰到好处。 UrlEncodedFormEntity 和 StringEntity 有什么区别。服务器上是否需要不同的设置?何时使用 UrlEncodedFormEntity 以及何时使用 StringEntity? 此解决方案可能不适用于某些站点,因为较旧的站点不接受 json 作为发布请求有效负载类型。【参考方案2】:

您是否尝试过不使用 JSON 对象并仅传递两个基本名称值对? 另外,它可能与您的服务器设置有关

更新: 这是我使用的一段代码:

InputStream is = null;
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
    nameValuePairs.add(new BasicNameValuePair("lastupdate", lastupdate)); 

try 
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost(connection);
        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        HttpResponse response = httpclient.execute(httppost);
        HttpEntity entity = response.getEntity();
        is = entity.getContent();
        Log.d("HTTP", "HTTP: OK");
     catch (Exception e) 
        Log.e("HTTP", "Error in http connection " + e.toString());
    

【讨论】:

我尝试只传递两个BasicNameValuePairs,但似乎仍然没有数据作为 POST 发送。难道请求是作为get发送的,因此服务器没有处理任何发布数据? HttpPost 应该确保不会发生这种情况,不是吗? 是的,这很像我最终得到的代码,在删除内容类型设置(我显然使用了太多)之后,正如我对原始帖子的评论中提到的那样。感谢您的帮助。【参考方案3】:

我刚刚检查过,我的代码和你一样,它工作得很好。 唯一的区别是我如何填写参数列表:

我使用的是:ArrayList&lt;BasicNameValuePair&gt; params

并以这种方式填写:

 params.add(new BasicNameValuePair("apikey", apikey);

我不使用任何 JSONObject 将参数发送到网络服务。

您有义务使用 JSONObject 吗?

【讨论】:

由于我正在与一位 Iphone 开发人员并行工作,并且他的应用程序实际上会发布数据,因此我别无选择,只能将数据提交为 JSON。我尝试只发送两个值对,但没有区别。【参考方案4】:

公共类 GetUsers 扩展 AsyncTask

    @Override
    protected void onPreExecute() 
        super.onPreExecute();

    

    private String convertStreamToString(InputStream is) 
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try 
            while ((line = reader.readLine()) != null) 
                sb.append(line + "\n");
            
         catch (IOException e) 
            e.printStackTrace();
         finally 
            try 
                is.close();
             catch (IOException e) 
                e.printStackTrace();
            
        

        return sb.toString();
    

    public String connect()
    
        HttpClient httpclient = new DefaultHttpClient();

        // Prepare a request object
        HttpPost htopost = new HttpPost("URL");
        htopost.setHeader(new BasicHeader("Authorization","Basic Og=="));

        try 

            JSONObject param = new JSONObject();
            param.put("PageSize",100);
            param.put("Userid",userId);
            param.put("CurrentPage",1);

            htopost.setEntity(new StringEntity(param.toString()));

            // Execute the request
            HttpResponse response;

            response = httpclient.execute(htopost);
            // Examine the response status
            // Get hold of the response entity
            HttpEntity entity = response.getEntity();

            if (entity != null) 

                // A Simple JSON Response Read
                InputStream instream = entity.getContent();
                String result = convertStreamToString(instream);

                // A Simple JSONObject Creation
                json = new JSONArray(result);

                // Closing the input stream will trigger connection release
                instream.close();
                return ""+response.getStatusLine().getStatusCode();
            
         catch (Exception e) 
            e.printStackTrace();
        

        return null;
    

    @Override
    protected String doInBackground(String... urls) 
        return connect();
    

    @Override
    protected void onPostExecute(String status)
        try 

            if(status.equals("200"))
            

                    Global.defaultMoemntLsit.clear();

                    for (int i = 0; i < json.length(); i++) 
                        JSONObject ojb = json.getJSONObject(i);
                        UserMomentModel u = new UserMomentModel();
                        u.setId(ojb.getString("Name"));
                        u.setUserId(ojb.getString("ID"));


                        Global.defaultMoemntLsit.add(u);
                    




                            userAdapter = new UserAdapter(getActivity(), Global.defaultMoemntLsit);
                            recycleView.setAdapter(userMomentAdapter);
                            recycleView.setLayoutManager(mLayoutManager);
           



        
        catch (Exception e)
        
            e.printStackTrace();

        
    

【讨论】:

这段代码与问题有什么关系? edit你的答案并添加解释

以上是关于在 Android 中使用带有 post 参数的 HttpClient 和 HttpPost的主要内容,如果未能解决你的问题,请参考以下文章

如何在android studio中通过带有密码的POST方法获取JSON数据

使用带有参数对象的 Axios Post 没有返回数据

带有 CRUD/Rest 的 Alamofire POST 参数

如何发送带有 URL 参数和 JSON 正文的 POST? [关闭]

使用带有参数的 NSURLSession (HTTP POST) 下载 PDF

Rest API Post Json 使用带有两个参数的 C#