在Android開發中網絡請求是最常用的操作之一, Android SDK中對HTTP(超文本傳輸協議)也提供了很好的支持,這裏包括兩種接口:
1、HttpURLConnection,可以實現簡單的基於URL請求、響應功能;
2、HttpClient,使用起來更方面更強大,使用方便,但是不易於擴展(不推薦使用)。
但在android API23的SDK中Google將HttpClient移除了。Google建議使用httpURLconnection進行網絡訪問操作。
HttpURLconnection是基於http協議的,支持get,post,put,delete等各種請求方式,最常用的就是get和post,下面針對這兩種請求方式進行講解。
以下是自己對HttpURLconnection進行了封裝。
HttpUtils代碼:
public class HttpUtils { private static ExecutorService threadPool = Executors.newCachedThreadPool(); private static final int HTTP_CONNECT_TIME=5000; private static final int HTTP_READ_TIME=10000; /** * GET請求返回數據會解析成字符串String * @param context context * @param urlPath 請求的路徑 * @param listener listener */ public static void doGet(final Context context, final String urlPath, final StringCallbackListener listener) { threadPool.execute(new Runnable() { @Override public void run() { URL url; HttpURLConnection httpURLConnection = null; try { // 根據URL地址創建URL對象 url = new URL(urlPath); // 獲取HttpURLConnection對象 httpURLConnection = ( HttpURLConnection ) url.openConnection(); // 設置請求方式,默認爲GET httpURLConnection.setRequestMethod("GET"); // 設置連接超時 httpURLConnection.setConnectTimeout(HTTP_CONNECT_TIME); // 設置讀取超時 httpURLConnection.setReadTimeout(HTTP_READ_TIME); // 響應碼爲200表示成功 if ( httpURLConnection.getResponseCode() == 200 ) { // 獲取網絡的輸入流 InputStream is = httpURLConnection.getInputStream(); BufferedReader bf = new BufferedReader(new InputStreamReader(is, "UTF-8")); StringBuffer buffer = new StringBuffer(); String line = ""; while ( (line = bf.readLine()) != null ) { buffer.append(line); } is.close(); bf.close(); new ResponseCall(context, listener).doSuccess(buffer.toString()); } else { new ResponseCall(context, listener).doFail( new NetworkErrorException("response error code:" + httpURLConnection.getResponseCode())); } } catch ( MalformedURLException e ) { if ( listener != null ) { new ResponseCall(context, listener).doFail(e); } } catch ( IOException e ) { if ( listener != null ) { new ResponseCall(context, listener).doFail(e); } } finally { if ( httpURLConnection != null ) { // 釋放資源 httpURLConnection.disconnect(); } } } }); } /** * GET請求返回數據會解析成byte[]數組 * @param context context * @param urlPath 請求的url * @param listener 回調監聽 */ public static void doGet(final Context context, final String urlPath, final BytesCallbackListener listener) { threadPool.execute(new Runnable() { @Override public void run() { URL url = null; HttpURLConnection httpURLConnection = null; try { // 根據URL地址創建URL對象 url = new URL(urlPath); // 獲取HttpURLConnection對象 httpURLConnection = ( HttpURLConnection ) url.openConnection(); // 設置請求方式,默認爲GET httpURLConnection.setRequestMethod("GET"); // 設置連接超時 httpURLConnection.setConnectTimeout(HTTP_CONNECT_TIME); // 設置讀取超時 httpURLConnection.setReadTimeout(HTTP_READ_TIME); // 響應碼爲200表示成功,否則失敗。 if ( httpURLConnection.getResponseCode() != 200 ) { new ResponseCall(context, listener).doFail( new NetworkErrorException("response error code:" + httpURLConnection.getResponseCode())); } else { // 獲取網絡的輸入流 InputStream is = httpURLConnection.getInputStream(); // 讀取輸入流中的數據 BufferedInputStream bis = new BufferedInputStream(is); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] bytes = new byte[1024]; int len = -1; while ( (len = bis.read(bytes)) != -1 ) { baos.write(bytes, 0, len); } bis.close(); is.close(); new ResponseCall(context, listener).doSuccess(baos.toByteArray()); } } catch ( MalformedURLException e ) { if ( listener != null ) { new ResponseCall(context, listener).doFail(e); } } catch ( IOException e ) { if ( listener != null ) { new ResponseCall(context, listener).doFail(e); } } finally { if ( httpURLConnection != null ) { httpURLConnection.disconnect(); } } } }); } /** * GET請求返回數據會解析成字符串 String * @param context context * @param urlPath 請求的路徑 * @param listener 回調監聽 * @param params 參數列表 */ public static void doPost(final Context context, final String urlPath, final StringCallbackListener listener, final Map<String, Object> params) { final StringBuffer buffer = new StringBuffer(); for (String key : params.keySet()) { if(buffer.length()!=0){ buffer.append("&"); } buffer.append(key).append("=").append(params.get(key)); } threadPool.execute(new Runnable() { @Override public void run() { URL url; HttpURLConnection httpURLConnection = null; try { url = new URL(urlPath); httpURLConnection = ( HttpURLConnection ) url.openConnection(); httpURLConnection.setRequestProperty("accept", "*/*"); httpURLConnection.setRequestProperty("connection", "Keep-Alive"); httpURLConnection.setRequestProperty("Content-Length", String .valueOf(buffer.length())); httpURLConnection.setRequestMethod("POST"); httpURLConnection.setConnectTimeout(HTTP_CONNECT_TIME); httpURLConnection.setReadTimeout(HTTP_READ_TIME); // 設置運行輸入 httpURLConnection.setDoInput(true); // 設置運行輸出 httpURLConnection.setDoOutput(true); PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream()); // 發送請求參數 printWriter.write(buffer.toString()); // flush輸出流的緩衝 printWriter.flush(); printWriter.close(); if ( httpURLConnection.getResponseCode() == 200 ) { // 獲取網絡的輸入流 InputStream is = httpURLConnection.getInputStream(); BufferedReader bf = new BufferedReader(new InputStreamReader(is, "UTF-8")); //最好在將字節流轉換爲字符流的時候 進行轉碼 StringBuffer buffer = new StringBuffer(); String line = ""; while ( (line = bf.readLine()) != null ) { buffer.append(line); } bf.close(); is.close(); new ResponseCall(context, listener).doSuccess(buffer.toString()); } else { new ResponseCall(context, listener).doFail( new NetworkErrorException("response error code:" + httpURLConnection.getResponseCode())); } } catch ( MalformedURLException e ) { if ( listener != null ) { new ResponseCall(context, listener).doFail(e); } } catch ( IOException e ) { if ( listener != null ) { new ResponseCall(context, listener).doFail(e); } } finally { if ( httpURLConnection != null ) { httpURLConnection.disconnect(); } } } }); } /** * GET請求 返回數據會解析成Byte[]數組 * @param context context * @param urlPath 請求的路徑 * @param listener 回調監聽 * @param params 參數列表 */ public static void doPost(final Context context, final String urlPath, final BytesCallbackListener listener, final Map<String, Object> params) { final StringBuffer buffer = new StringBuffer(); for (String key : params.keySet()) { if(buffer.length()!=0){ buffer.append("&"); } buffer.append(key).append("=").append(params.get(key)); } threadPool.execute(new Runnable() { @Override public void run() { URL url; HttpURLConnection httpURLConnection = null; try { url = new URL(urlPath); httpURLConnection = ( HttpURLConnection ) url.openConnection(); httpURLConnection.setRequestProperty("accept", "*/*"); httpURLConnection.setRequestProperty("connection", "Keep-Alive"); httpURLConnection.setRequestProperty("Content-Length", String .valueOf(buffer.length())); httpURLConnection.setRequestMethod("POST"); httpURLConnection.setConnectTimeout(HTTP_CONNECT_TIME); httpURLConnection.setReadTimeout(HTTP_READ_TIME); // 設置運行輸入 httpURLConnection.setDoInput(true); // 設置運行輸出 httpURLConnection.setDoOutput(true); PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream()); // 發送請求參數 printWriter.write(buffer.toString()); // flush輸出流的緩衝 printWriter.flush(); printWriter.close(); if ( httpURLConnection.getResponseCode() == 200 ) { // 獲取網絡的輸入流 InputStream is = httpURLConnection.getInputStream(); // 讀取輸入流中的數據 BufferedInputStream bis = new BufferedInputStream(is); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] bytes = new byte[1024]; int len = -1; while ( (len = bis.read(bytes)) != -1 ) { baos.write(bytes, 0, len); } bis.close(); is.close(); // 響應的數據 new ResponseCall(context, listener).doSuccess(baos.toByteArray()); } else { new ResponseCall(context, listener).doFail( new NetworkErrorException("response error code:" + httpURLConnection.getResponseCode())); } } catch ( MalformedURLException e ) { if ( listener != null ) { new ResponseCall(context, listener).doFail(e); } } catch ( IOException e ) { if ( listener != null ) { new ResponseCall(context, listener).doFail(e); } } finally { if ( httpURLConnection != null ) { httpURLConnection.disconnect(); } } } }); } }
ResponseCall<T> 代碼:
public class ResponseCall<T> { private static final int FAIL = 0; private static final int SUCCESS = 1; private Handler mHandler; public ResponseCall(Context context, final BytesCallbackListener listener) { Looper looper = context.getMainLooper(); mHandler = new Handler(looper) { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if ( msg.what == FAIL ) { //成功 listener.onSuccess(( byte[] ) msg.obj); } else if ( msg.what == SUCCESS ) { //失敗 listener.onError(( Exception ) msg.obj); } } }; } public ResponseCall(Context context, final StringCallbackListener listener) { Looper looper = context.getMainLooper(); mHandler = new Handler(looper) { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if ( msg.what == FAIL ) { //成功 listener.onSuccess(msg.obj.toString()); } else if ( msg.what == SUCCESS ) { //失敗 listener.onError(( Exception ) msg.obj); } } }; } public void doSuccess(T response) { Message message = Message.obtain(); message.obj = response; message.what = FAIL; mHandler.sendMessage(message); } public void doFail(Exception e) { Message message = Message.obtain(); message.obj = e; message.what = SUCCESS; mHandler.sendMessage(message); } }
BytesCallbackListener:
public interface BytesCallbackListener { // 網絡請求成功 void onSuccess(byte[] response); // 網絡請求失敗 void onError(Exception e); }
StringCallbackListener:
public interface StringCallbackListener { // 網絡請求成功 void onSuccess(String response); // 網絡請求失敗 void onError(Exception e); }