android網路訪問之HttpURLConnection vs OkHttp
阿新 • • 發佈:2019-02-19
首先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);