Java Android HTTP实现总结
Http(Hypertext Transfer Protocol)超文本传输协议,是一个基于请求/响应模式的无状态的协议,Http1.1版给出了持续连接的机制,客户端建立连接之后,可以发送多次请求,当不会再发送时再关闭连接。
Android使用Java,对于Http协议的基本功能有两种实现方案:
1.使用JDK的java.net包下的HttpURLConnection.
2.使用Apache的HttpClient。
关于二者的比较可以看一下:
http://www.cnblogs.com/devinzhang/archive/2012/01/17/2325092.html
Android SDK中集成了Apache的HttpClient模块,也即说Android上两种方法都能用。
之前看一个Android开发者博客(原文链接先空缺,需要FQ)对此的讨论,大意总结如下:
1.HttpClient的功能比较全,更加强大;而HttpURLConnection的功能较简单和原始,但是性能更好。
2.在Android 2.x的版本中使用HttpURLConnection有bug,但是后来高级版本的Android已经将带来的bug修复,并且做了一些进一步优化的工作,所以建议在高级版本的Android系统(Android 2.3之后)使用HttpURLConnection,低版本的系统仍使用HttpClient。
程序实现
下面来讨论一下实现,首先,需要确认Manifest中有权限:
<uses-permission android:name="android.permission.INTERNET" />
使用JDK的HttpURLConnection类
HttpURLConnection参考:
http://developer.android.com/reference/java/net/HttpURLConnection.html
使用这个类的一般步骤:
1.通过URL.openConnection() 方法获取一个HttpURLConnection对象,并且将结果强制转化为HttpURLConnection类型。
2.准备请求(prepare the request),包括URI,headers中的各种属性等
(Request headers may also include metadata such as credentials, preferred content types, and session cookies.)
3.请求体(optionally)。如果有请求体那么setDoOutput(true)必须为true,然后把输入放在getOutputStream()流中。
4.读取响应。响应的headers一般包括了一些metadata比如响应体的内容类型和长度,修改日期以及session cookies。响应体可以从 getInputStream()流中读出。
5.断开连接。响应体被读出之后,应该调用 disconnect()方法来断开连接。
例子代码:
package com.example.helloandroidhttp; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.Map; import android.util.Log; public class HttpUtilsJDK { private static final String LOG_TAG = "Http->JDK"; private static final int CONNECT_TIME_OUT = 3000; private static final String HEADER_CONTENT_TYPE = "Content-Type"; private static final String HEADER_CONTENT_LENGTH = "Content-Length"; /** * Default encoding for POST or PUT parameters. See * {@link #getParamsEncoding()}. */ private static final String DEFAULT_PARAMS_ENCODING = "UTF-8"; public static String getParamsEncoding() { return DEFAULT_PARAMS_ENCODING; } public static String getBodyContentType() { return "application/x-www-form-urlencoded; charset=" + getParamsEncoding(); } public static String performGetRequest(String baseUrl) { String result = null; HttpURLConnection connection = null; try { URL url = new URL(baseUrl); if (null != url) { // 获取HttpURLConnection类型的对象 connection = (HttpURLConnection) url.openConnection(); // 设置连接的最大等待时间 connection.setConnectTimeout(CONNECT_TIME_OUT); // Sets the maximum time to wait for an input stream read to // complete before giving up. connection.setReadTimeout(3000); // 设置为GET方法 connection.setRequestMethod("GET"); connection.setDoInput(true); if (200 == connection.getResponseCode()) { InputStream inputStream = connection.getInputStream(); result = getResultString(inputStream, getParamsEncoding()); } else { Log.e(LOG_TAG, "Connection failed: " + connection.getResponseCode()); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { connection.disconnect(); } return result; } public static String performPostRequest(String baseUrl, Map<String, String> params) { String result = null; HttpURLConnection connection = null; try { URL url = new URL(baseUrl); if (null != url) { // 获取HttpURLConnection类型的对象 connection = (HttpURLConnection) url.openConnection(); // 设置响应超时限制 connection.setConnectTimeout(CONNECT_TIME_OUT); // 设置为POST方法 connection.setRequestMethod("POST"); connection.setDoInput(true); // 有请求体则setDoOutput(true)必须设定 connection.setDoOutput(true); // 为了性能考虑,如果包含请求体,那么最好调用 setFixedLengthStreamingMode(int)或者 // setChunkedStreamingMode(int) // connection.setChunkedStreamingMode(0);// 参数为0时使用默认值 byte[] data = getParamsData(params); connection.setRequestProperty(HEADER_CONTENT_TYPE, getBodyContentType()); if (null != data) { connection.setFixedLengthStreamingMode(data.length); connection.setRequestProperty(HEADER_CONTENT_LENGTH, String.valueOf(data.length)); OutputStream outputStream = connection.getOutputStream(); outputStream.write(data); } // 得到返回值 int responseCode = connection.getResponseCode(); if (200 == responseCode) { result = getResultString(connection.getInputStream(), getParamsEncoding()); } else { Log.e(LOG_TAG, "Connection failed: " + connection.getResponseCode()); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { connection.disconnect(); } return result; } private static byte[] getParamsData(Map<String, String> params) { byte[] data = null; try { if (null != params && !params.isEmpty()) { StringBuffer buffer = new StringBuffer(); for (Map.Entry<String, String> entry : params.entrySet()) { buffer.append(entry.getKey()) .append("=") .append(URLEncoder.encode(entry.getValue(), getParamsEncoding())).append("&");// 请求的参数之间使用&分割。 } // 最后一个&要去掉 buffer.deleteCharAt(buffer.length() - 1); data = buffer.toString().getBytes(getParamsEncoding()); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return data; } private static String getResultString(InputStream inputStream, String encode) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] data = new byte[1024]; int len = 0; String result = ""; if (inputStream != null) { try { while ((len = inputStream.read(data)) != -1) { outputStream.write(data, 0, len); } result = new String(outputStream.toByteArray(), encode); } catch (IOException e) { e.printStackTrace(); } } return result; } }