1. 程式人生 > >android網路訪問之HttpURLConnection vs OkHttp

android網路訪問之HttpURLConnection vs OkHttp

首先HttpURLConnection是原生的android網路訪問的API,而OkHttp則是第三方的包;

其次,測試發現這兩種方法,如果是廣泛認可的證書所認證的https網址,可以正常獲取到,如果是比較小眾的,也就是相當於程式碼裡沒有備案的證書,則訪問不到。

1、HttpURLConnection的使用:

<1>基本用法:
package zjava.data.request;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;

import zjava.sysutil.Common;

import android.util.Log;
/**
 * 原生的網路請求
 * 使用網路類必須要在Manifest裡面新增:
 * <uses-permission android:name="android.permission.INTERNET" />
 * @author wzj
 *
 */
public class HttpUrlConn {
	
	public static void requestGet(String baseUrl,HashMap<String, String> paramsMap) {
		// 如果有引數的話,並且忘記了?則給加上
		if(baseUrl != null && !baseUrl.endsWith("?") && !paramsMap.isEmpty())
			baseUrl = baseUrl+"?";
		
		HttpUrlConn conn = new HttpUrlConn();
		new Thread(conn.new HttpRequestGetRunnable(baseUrl, paramsMap)).start();
    }
	
	public static void requestPost(String baseUrl,HashMap<String, String> paramsMap) {
        HttpUrlConn conn = new HttpUrlConn();
        new Thread(conn.new HttpRequestPostRunnable(baseUrl, paramsMap)).start();
    }
	
	/**
     * 將輸入流轉換成字串
     *
     * @param is 從網路獲取的輸入流
     * @return
     */
    public static String streamToString(InputStream is) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            baos.close();
            is.close();
            byte[] byteArray = baos.toByteArray();
            return new String(byteArray);
        } catch (Exception e) {
            Log.v(Common.MSG_ZJAVA, e.toString());
            return null;
        }
    }
    
    class HttpRequestGetRunnable implements Runnable
    {
    	private String baseUrl;
    	private HashMap<String, String> paramsMap;
    	
    	public HttpRequestGetRunnable(String baseUrl,HashMap<String, String> paramsMap)
    	{
    		this.baseUrl = baseUrl;
    		this.paramsMap = paramsMap;
    	}
    	
		@Override
		public void run() {
			try
			{
				StringBuilder tempParams = new StringBuilder();
	            int pos = 0;
	            for (String key : paramsMap.keySet()) {
	                if (pos > 0) {
	                    tempParams.append("&");
	                }
	                tempParams.append(String.format("%s=%s", key, URLEncoder.encode(paramsMap.get(key),"utf-8")));
	                pos++;
	            }
	            String requestUrl = baseUrl + tempParams.toString();
	            // 新建一個URL物件
	            URL url = new URL(requestUrl);
	            // 開啟一個HttpURLConnection連線
	            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
	            // 設定連線主機超時時間
	            urlConn.setConnectTimeout(5 * 1000);
	            //設定從主機讀取資料超時
	            urlConn.setReadTimeout(5 * 1000);
	            // 設定是否使用快取  預設是true
	            urlConn.setUseCaches(true);
	            // 設定為Post請求
	            urlConn.setRequestMethod("GET");
	            //urlConn設定請求頭資訊
	            //設定請求中的媒體型別資訊。
	            //urlConn.setRequestProperty("Content-Type", "application/json");
	            //設定客戶端與服務連線型別
	            urlConn.addRequestProperty("Connection", "Keep-Alive");
	            // 開始連線
	            urlConn.connect();
	            // 判斷請求是否成功
	            if (urlConn.getResponseCode() == 200) {
	                // 獲取返回的資料
	                String result = streamToString(urlConn.getInputStream());
	                Log.v(Common.MSG_ZJAVA, "Get方式請求成功,result--->" + result);
	            } else {
	                Log.v(Common.MSG_ZJAVA, "Get方式請求失敗");
	            }
	            // 關閉連線
	            urlConn.disconnect();
			}catch(Exception e)
			{
				Log.v(Common.MSG_ZJAVA, e.toString());
			}
		}
    	
    }
    
    class HttpRequestPostRunnable implements Runnable
    {
    	private String baseUrl;
    	private HashMap<String, String> paramsMap;
    	
    	
    	public HttpRequestPostRunnable(String baseUrl,HashMap<String, String> paramsMap)
    	{
    		this.baseUrl = baseUrl;
    		this.paramsMap = paramsMap;
    	}
    	
		@Override
		public void run() {
			try {
	            //合成引數
	            StringBuilder tempParams = new StringBuilder();
	            int pos = 0;
	            for (String key : paramsMap.keySet()) {
	                if (pos > 0) {
	                    tempParams.append("&");
	                }
	                tempParams.append(String.format("%s=%s", key,  URLEncoder.encode(paramsMap.get(key),"utf-8")));
	                pos++;
	            }
	            String params =tempParams.toString();
	            // 請求的引數轉換為byte陣列
	            byte[] postData = params.getBytes();
	            // 新建一個URL物件
	            URL url = new URL(baseUrl);
	            // 開啟一個HttpURLConnection連線
	            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
	            // 設定連線超時時間
	            urlConn.setConnectTimeout(5 * 1000);
	            //設定從主機讀取資料超時
	            urlConn.setReadTimeout(5 * 1000);
	            // Post請求必須設定允許輸出 預設false
	            urlConn.setDoOutput(true);
	            //設定請求允許輸入 預設是true
	            urlConn.setDoInput(true);
	            // Post請求不能使用快取
	            urlConn.setUseCaches(false);
	            // 設定為Post請求
	            urlConn.setRequestMethod("POST");
	            //設定本次連線是否自動處理重定向
	            urlConn.setInstanceFollowRedirects(true);
	            // 配置請求Content-Type
	            //urlConn.setRequestProperty("Content-Type", "application/json");
	            // 開始連線
	            urlConn.connect();
	            // 傳送請求引數
	            DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());
	            dos.write(postData);
	            dos.flush();
	            dos.close();
	            // 判斷請求是否成功
	            if (urlConn.getResponseCode() == 200) {
	                // 獲取返回的資料
	                String result = streamToString(urlConn.getInputStream());
	                Log.v(Common.MSG_ZJAVA, "Post方式請求成功,result--->" + result);
	            } else {
	                Log.v(Common.MSG_ZJAVA, "Post方式請求失敗");
	            }
	            // 關閉連線
	            urlConn.disconnect();
	        } catch (Exception e) {
	            Log.v(Common.MSG_ZJAVA, e.toString());
	        }
		}
    	
    }

}

這裡參考了大神的文章,原文連結:

http://www.cnblogs.com/whoislcj/p/5520384.html

呼叫:

HttpUrlConn.requestPost("http://yourdomain.com/push_url", new HashMap<String, String>());//post呼叫不帶引數也要new一個map

get也一樣,把函式換成requestGet就可以了。

<2>封裝並且新增https支援
package zjava.data.request;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import zjava.sysutil.Common;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;
/**
 * 原生的網路請求
 * 使用網路類必須要在Manifest裡面新增:
 * <uses-permission android:name="android.permission.INTERNET" />
 * @author wzj
 *
 */
public class HttpUrlConn 
{
	
	public static void requestGet(String baseUrl,HashMap<String, String> paramsMap,ResultCallback callback) {
		// 如果有引數的話,並且忘記了?則給加上
		if(baseUrl != null && !baseUrl.endsWith("?") && !paramsMap.isEmpty())
			baseUrl = baseUrl+"?";
		
		HttpUrlConn conn = new HttpUrlConn();
		new Thread(conn.new HttpRequestGetRunnable(baseUrl, paramsMap,callback)).start();
    }
	
	public static void requestPost(String baseUrl,HashMap<String, String> paramsMap,ResultCallback callback) {
        HttpUrlConn conn = new HttpUrlConn();
        new Thread(conn.new HttpRequestPostRunnable(baseUrl, paramsMap,callback)).start();
    }
	
	/**
     * 將輸入流轉換成字串
     *
     * @param is 從網路獲取的輸入流
     * @return
     */
    public static String streamToString(InputStream is) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            baos.close();
            is.close();
            byte[] byteArray = baos.toByteArray();
            return new String(byteArray);
        } catch (Exception e) {
            Log.v(Common.MSG_ZJAVA, e.toString());
            return null;
        }
    }
    
    class HttpRequestGetRunnable implements Runnable
    {
    	private String baseUrl;
    	private HashMap<String, String> paramsMap;
    	private ResultCallback callback;
    	private Handler handler;
    	
    	public HttpRequestGetRunnable(String baseUrl,HashMap<String, String> paramsMap,ResultCallback callback)
    	{
    		this.baseUrl = baseUrl;
    		this.paramsMap = paramsMap;
    		this.callback = callback;
    		handler = new Handler(Looper.getMainLooper());
    	}
    	
		@Override
		public void run() {
			try
			{
				StringBuilder tempParams = new StringBuilder();
	            int pos = 0;
	            for (String key : paramsMap.keySet()) {
	                if (pos > 0) {
	                    tempParams.append("&");
	                }
	                tempParams.append(String.format("%s=%s", key, URLEncoder.encode(paramsMap.get(key),"utf-8")));
	                pos++;
	            }
	            String requestUrl = baseUrl + tempParams.toString();
	            // 新建一個URL物件
	            URL url = new URL(requestUrl);
	            
	            //設定https
	            SSLContext sc = SSLContext.getInstance("TLS");
	            sc.init(null, new TrustManager[]{new MyTrustManager()},new SecureRandom());
	            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	            HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());
	            
	            // 開啟一個HttpURLConnection連線
	            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
	            // 設定連線主機超時時間
	            urlConn.setConnectTimeout(5 * 1000);
	            //設定從主機讀取資料超時
	            urlConn.setReadTimeout(5 * 1000);
	            // 設定是否使用快取  預設是true
	            urlConn.setUseCaches(true);
	            // 設定為Post請求
	            urlConn.setRequestMethod("GET");
	            //urlConn設定請求頭資訊
	            //設定請求中的媒體型別資訊。
	            //urlConn.setRequestProperty("Content-Type", "application/json");
	            //設定客戶端與服務連線型別
	            urlConn.addRequestProperty("Connection", "Keep-Alive");
	            // 開始連線
	            urlConn.connect();
	            // 判斷請求是否成功
	            if (urlConn.getResponseCode() == 200) {
	                // 獲取返回的資料
	                final String result = streamToString(urlConn.getInputStream());
	                handler.post(new Runnable() {
						
						@Override
						public void run() {
							callback.onResponse(result);
						}
					});
	                
	                
	            } else {
	            	handler.post(new Runnable() {
						
						@Override
						public void run() {
							callback.onError("Get方式請求失敗");
						}
					});
	            	
	            }
	            // 關閉連線
	            urlConn.disconnect();
			}catch(final Exception e)
			{
				
				handler.post(new Runnable() {
					
					@Override
					public void run() {
						callback.onError(e.toString());
					}
				});
			}
		}
    	
    }
    
    class HttpRequestPostRunnable implements Runnable
    {
    	private String baseUrl;
    	private HashMap<String, String> paramsMap;
    	private ResultCallback callback;
    	private Handler handler;
    	
    	public HttpRequestPostRunnable(String baseUrl,HashMap<String, String> paramsMap,ResultCallback callback)
    	{
    		this.baseUrl = baseUrl;
    		this.paramsMap = paramsMap;
    		this.callback = callback;
    		handler = new Handler(Looper.getMainLooper());
    	}
    	
		@Override
		public void run() {
			try {
	            //合成引數
	            StringBuilder tempParams = new StringBuilder();
	            int pos = 0;
	            for (String key : paramsMap.keySet()) {
	                if (pos > 0) {
	                    tempParams.append("&");
	                }
	                tempParams.append(String.format("%s=%s", key,  URLEncoder.encode(paramsMap.get(key),"utf-8")));
	                pos++;
	            }
	            String params =tempParams.toString();
	            // 請求的引數轉換為byte陣列
	            byte[] postData = params.getBytes();
	            // 新建一個URL物件
	            URL url = new URL(baseUrl);
	            
	            //設定https
	            SSLContext sc = SSLContext.getInstance("TLS");
	            sc.init(null, new TrustManager[]{new MyTrustManager()},new SecureRandom());
	            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	            HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());
	            
	            // 開啟一個HttpURLConnection連線
	            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
	            // 設定連線超時時間
	            urlConn.setConnectTimeout(5 * 1000);
	            //設定從主機讀取資料超時
	            urlConn.setReadTimeout(5 * 1000);
	            // Post請求必須設定允許輸出 預設false
	            urlConn.setDoOutput(true);
	            //設定請求允許輸入 預設是true
	            urlConn.setDoInput(true);
	            // Post請求不能使用快取
	            urlConn.setUseCaches(false);
	            // 設定為Post請求
	            urlConn.setRequestMethod("POST");
	            //設定本次連線是否自動處理重定向
	            urlConn.setInstanceFollowRedirects(true);
	            // 配置請求Content-Type
	            //urlConn.setRequestProperty("Content-Type", "application/json");
	            // 開始連線
	            urlConn.connect();
	            // 傳送請求引數
	            DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());
	            dos.write(postData);
	            dos.flush();
	            dos.close();
	            // 判斷請求是否成功
	            if (urlConn.getResponseCode() == 200) {
	                // 獲取返回的資料
	                final String result = streamToString(urlConn.getInputStream());
	                handler.post(new Runnable() {
						
						@Override
						public void run() {
							callback.onResponse(result);
						}
					});
	            } else {
	            	handler.post(new Runnable() {
						
						@Override
						public void run() {
							callback.onError("Post方式請求失敗");
						}
					});
	            }
	            // 關閉連線
	            urlConn.disconnect();
	        } catch (final Exception e) {
	            Log.v(Common.MSG_ZJAVA, e.toString());
	            handler.post(new Runnable() {
					@Override
					public void run() {
						callback.onError(e.toString());
					}
				});
	        }
		}
    	
    }
    
  
	private class MyHostnameVerifier implements HostnameVerifier
	{  
        @Override  
        public boolean verify(String hostname, SSLSession session) 
        {  
            return true;  
        }
	}  
  
	private class MyTrustManager implements X509TrustManager
	{  
	
        @Override  
        public X509Certificate[] getAcceptedIssuers() {  
            return null;  
        }

		@Override
		public void checkClientTrusted(X509Certificate[] arg0,
				String arg1) throws CertificateException {
		}

		@Override
		public void checkServerTrusted(X509Certificate[] arg0,
				String arg1) throws CertificateException {
		}
	}
	
	
	public static abstract class ResultCallback
    {
        public abstract void onError(String e);

        public abstract void onResponse(String response);
    }

}


呼叫:

    	HttpUrlConn.requestPost("https://yourdomain.com", new HashMap<String, String>(), new HttpUrlConn.ResultCallback() {
			
			@Override
			public void onResponse(String response) {
				// TODO Auto-generated method stub
				Log.v(Common.MSG_ZJAVA, "Post方式請求成功,result--->" + response);
				//Toast.makeText(context, "hello world!", Toast.LENGTH_LONG);
			}
			
			@Override
			public void onError(String e) {
				// TODO Auto-generated method stub
				Log.v(Common.MSG_ZJAVA, e);
				
			}
		});


2、OkHttp基礎用法

<1>下載okhttp和他所依賴的okio的jar包,放到libs裡面

<2>get和post請求程式碼如下:

package zjava.data.request;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import zjava.sysutil.Common;


import android.util.Log;

import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

public class OkHttpConn {
	
	public static void requestGet(String url)
	{
		//建立okHttpClient物件
		OkHttpClient mOkHttpClient = new OkHttpClient();
		//建立一個Request
		final Request request = new Request.Builder()
        	.url(url)
        	.build();
		//new call
		Call call = mOkHttpClient.newCall(request); 
		//請求加入排程
		call.enqueue(new Callback()
		        {
					@Override
					public void onFailure(Request request, IOException exception) {
						Log.v(Common.MSG_ZJAVA, "失敗");
					}

					@Override
					public void onResponse(Response response) throws IOException {
						Log.v(Common.MSG_ZJAVA, response.body().string());
					}
		        }); 
	}
	
	public static void requestPost(String url,HashMap<String, String> params)
	{
		//建立OkHttpClient物件
		OkHttpClient mOkHttpClient = new OkHttpClient();
		//通過FormEncodingBuilder物件新增多個請求引數鍵值對
		FormEncodingBuilder builder = new FormEncodingBuilder();
		Iterator iterator = params.entrySet().iterator();
		while(iterator.hasNext())
		{
			Map.Entry<String,String> entry = (Map.Entry) iterator.next();
			builder.add(entry.getKey(), entry.getValue());
		}
		//通過FormEncodingBuilder物件構造Post請求體
		RequestBody body = builder.build();
		//通過請求地址和請求體構造Post請求物件Request
		Request request = new Request.Builder().url(url).post(body).build();
		
		// 下面一樣
		Call call = mOkHttpClient.newCall(request); 
		//請求加入排程
		call.enqueue(new Callback()
		        {
					@Override
					public void onFailure(Request request, IOException exception) {
						Log.v(Common.MSG_ZJAVA, "失敗");
					}

					@Override
					public void onResponse(Response response) throws IOException {
						Log.v(Common.MSG_ZJAVA, response.body().string());
						
					}
		        }); 
	}
}


呼叫方法很簡單這裡就不說了。

3、okhttp的再次封裝

參見大神寫的,我直接拿來用了:

教程:

http://blog.csdn.net/lmj623565791/article/details/47911083

程式碼:

https://github.com/hongyangAndroid/okhttputils

注意:

<1>要使用這個程式碼需要新增2個類,一個是主要的類OkHttpClientManager,另一個是裡面用到的ImageUtils,其他的可以不管。

<2>由於這個類用到了google的json解析工具,所以要匯入Gson類庫。

<3>這樣使用:

get->

    	OkHttpClientManager.getAsyn("http://yourdomain.com/push_url",new OkHttpClientManager.ResultCallback<String>() 
    			{

			@Override
			public void onError(Request request, Exception e) {
				
			}

			@Override
			public void onResponse(String response) {
				// TODO Auto-generated method stub
				Log.v(Common.MSG_ZJAVA, response);
			}
		});

post->
    	HashMap<String, String> params = new HashMap<String, String>();
    	params.put("m", "p");
    	params.put("k", "myvalue");
    	
    	OkHttpClientManager.postAsyn("http://yourdomain.com/push_url", new OkHttpClientManager.ResultCallback<String>() {

			@Override
			public void onError(Request request, Exception e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void onResponse(String response) {
				// TODO Auto-generated method stub
				Log.v(Common.MSG_ZJAVA, response);
			}
		}, params);