DefaultHttpClient和HttpPost等已被弃用,现在该如何提交(post)数据?

4
在Android API 22之前,我只需要简单地执行以下操作:
/**
 * 
 * @param url
 * @param params
 * @return
 * @throws ClientProtocolException
 * @throws IOException
 */
public InputStream getStreamFromConnection(String url, List<NameValuePair> params) throws ClientProtocolException, IOException {
    if(ConnectionDetector.isConnectedToInternet(this.context)) {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new UrlEncodedFormEntity(params, "utf-8"));

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

        return httpEntity.getContent();
    } else {
        return null;
    }
}

以上代码中几乎所有的内容都已经过时了(包括NameValuePair, DefaultHttpClient, HttpPost, UrlEncodedFormEntity, HttpResponse, HttpEntity, ClientProtocolException),而在API 22+中我也找不到推荐的方法来进行POST请求。那么现在应该如何进行POST请求呢?


1
请查看此帖子,这是发送数据的新方式 http://stackoverflow.com/a/31548224/4987172 - Rene Limon
1
请尝试使用http://square.github.io/okhttp/。 - eddykordo
1
ن½؟用HttpUrlConnectionوˆ–و‌¥è‡ھSquareçڑ„okhttpم€‚ - Raghunandan
尝试使用Volley。它会自动处理在不同API级别中使用的所有连接类。http://developer.android.com/training/volley/index.html - Sayem
使用 Retrofit!让你的生活更轻松。 http://square.github.io/retrofit/ - Roee
4个回答

5
这是一个使用POST方法的异步任务示例:
private class SendMessageTask extends AsyncTask<String, Void, String> {

    Graduate targetGraduate;

    public SendMessageTask(Graduate targetGraduate){
        this.targetGraduate = targetGraduate;

    }

    @Override
    protected String doInBackground(String... params) {
        URL myUrl = null;
        HttpURLConnection conn = null;
        String response = "";
        String data = params[0];

        try {
            myUrl = new URL("http://your url");
            conn = (HttpURLConnection) myUrl.openConnection();
            conn.setReadTimeout(10000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);

            //one long string, first encode is the key to get the  data on your web 
            //page, second encode is the value, keep concatenating key and value.
            //theres another ways which easier then this long string in case you are 
            //posting a lot of info, look it up.
            String postData = URLEncoder.encode("TOKEN", "UTF-8") + "=" +
                    URLEncoder.encode(targetGraduate.getToken(), "UTF-8") + "&" +
                    URLEncoder.encode("SENDER_ID", "UTF-8") + "=" +
                    URLEncoder.encode(MainActivity.curretUser.getId(), "UTF-8") + "&" +
                    URLEncoder.encode("MESSAGE_DATA", "UTF-8") + "=" +
                    URLEncoder.encode(data, "UTF-8");
            OutputStream os = conn.getOutputStream();

            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
            bufferedWriter.write(postData);
            bufferedWriter.flush();
            bufferedWriter.close();

            InputStream inputStream = conn.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                response += line;
            }
            bufferedReader.close();
            inputStream.close();
            conn.disconnect();
            os.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return response;
    }

    @Override
    protected void onPostExecute(String s) {
        //do what ever you want with the response
        Log.d("roee", s);
    }
}

5

到目前为止,我一直使用名称值对。我无法再更改服务器端了。我半年前实现了所有内容。因此,到达的数据需要保持不变。使用HttpURLConnection,我可以发送字符串,因此我必须格式化我的字符串,以便结果也像使用名称值对时一样。我是正确的吗? - Mulgard
@Aakash 你能否看一下我的问题 http://stackoverflow.com/questions/40010099/how-to-post-multi-part-form-images-with-string-paramater-in-android/40012227?noredirect=1#comment67307125_40012227 - Gaurav Sarma

1

我使用哈希表而不是列表。这是我的做法:

HashMap<String,String> contact=new HashMap<>();
contact.put("name",name);
contact.put("address",add);

try{
    URL url=new URL(strURL);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("POST");
    conn.setDoInput(true);
    conn.setDoOutput(true);

    OutputStream os = conn.getOutputStream();
    BufferedWriter writer = new BufferedWriter(
                        new OutputStreamWriter(os, "UTF-8"));
    writer.write(postDataStr(contact));

    writer.flush();
    writer.close();
    os.close();

    int responseCode=conn.getResponseCode();
    conn.disconnect();
    if (responseCode == HttpURLConnection.HTTP_OK)
        return "success";
    else
        return "";
}catch (Exception e)
{
    e.printStackTrace();
}

postDataStr()函数用于将Hashmap转换为编码字符串,我从某处复制了这个函数并对其进行了修改以适应我的应用程序。以下是该代码:

private String postDataStr(HashMap<String, String> params) throws UnsupportedEncodingException{
    StringBuilder result = new StringBuilder();
    boolean first = true;
    for(Map.Entry<String, String> entry : params.entrySet()){
        if (first)
            first = false;
        else
            result.append("&");

        result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
        result.append("=");
        result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
    }

    return result.toString();
}

0
虽然这里的所有伟大回答都会解决您的问题,但我强烈建议您查看一些很棒(并且广泛使用的)网络库,因为它们可以减少您的工作量以及与Android进程和方向更改、进程终止等相关的错误情况。您应该查看Square的Retrofit库或Google自己的Volley用于网络连接。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接