Android-HttpClient連線網路獲取資料
阿新 • • 發佈:2019-01-27
大部分Android App都使用HttpURLConnection 和 Apache
HTTP Client來發送和接收網路資料(不包括第三方開源專案),這兩者都支援HTTPS,流上傳和下載,可配置超時,IPv6和連線池。
1)關於Apache HTTP Client:
DefaultHttpClient(android5.1\external\apache-http\src\org\apache\http\impl\client\DefaultHttpClient.java)和
AndroidHttpClient(android5.1\frameworks\base\core\java\android\net\http\AndroidHttpClient.java)都繼承於HttpClient。它們有龐大且靈活的API,還比較穩定,儘管有少量的bug。然而在不破壞它們相容性的前提下,它們龐大的API卻阻礙了它們得到進一步的改進和提升。為此,Android
團隊慢慢開始放棄Apache HTTP Client,在Android 6.0中,已經移除了Apache HTTP Client,在Android 官方文件中可查: http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-apache-http-client。
2)關於HttpURLConnection:
HttpURLConnection的是一個通用的,適用於大多數應用的輕量級HTTP客戶端。這個類出現的時候比較低調,因為其早期版本會有一些bug,但其專注的API使得它們很容易被穩步改善。在升級到Android2.2之前,HttpURLConnection有些令人沮喪的錯誤,特別是,在一個可讀的InputStream中呼叫close(),可能會毒害這個連結池。為此需要禁用連線池:
HttpURLConnection。
(2)準備request:request主要屬性是它的url。request header可以包括metadata,比如憑證(credentials),首選內容型別和session cookies。
(3)選擇性的上傳request的主體,如果它們包括一個request body,例項物件必須設定setDoOutput(true)。被寫入到stream的傳輸資料通過getOutputStream返回。
(4)讀取response,response header通常包括metadata,如response主體內容型別和長度、修改日期和session cookies。response主體可能從通過getInputStream返回的stream中讀取的。如果response沒有主體,該方法返回一個空的stream。
(5)斷開:一旦response主體被讀取到,HttpURLConnection應該呼叫disconnect()來斷開,釋放連線所持有的資源。
參考:http://developer.android.com/training/basics/network-ops/connecting.html http://developer.android.com/reference/java/net/HttpURLConnection.html http://developer.android.com/training/basics/network-ops/managing.html
privatevoid disableConnectionReuseIfNecessary(){
// HTTP connection reuse which was buggy pre-froyo
if(Integer.parseInt(Build.VERSION.SDK)<Build.VERSION_CODES.FROYO){
System.setProperty("http.keepAlive","false");
}
}
使用HttpURLConnection類::
(1)使用Url.openConnection()來獲得一個新的綜合上述,以HttpURLConnection為例來實現簡單連線網路獲取資料:1)首先在Manifest檔案中增加訪問網路的許可權:
<uses-permissionandroid:name="android.permission.INTERNET"/>
<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>
2)檢測手機聯網的狀態,手機可能沒有聯網,連線了網路,還要區分是移動資料還是WIFI。同時在網路連線發生變化時,需要接受系統的廣播:
android.net.conn.CONNECTIVITY_CHANGE,所以需要註冊廣播。這裡簡單的用一個類來管理網路連線的狀態:
public class NetConnectMananger {
private Context mContext;
private ConnectivityManager cm;
private NetworkInfo networkInfo;
private NetWorkChangedReceiver mNetWorkChangedReceiver;
//判斷是否是WIFI連線網路
private static boolean isWifiConnected = false;
//判斷是否是移動資料連線網路
private static boolean isMobileConnected = false;
public NetConnectMananger(Context context){
mContext = context;
cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
setMobileType();
//動態註冊廣播
mNetWorkChangedReceiver = new NetWorkChangedReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
context.registerReceiver(mNetWorkChangedReceiver, intentFilter);
}
public boolean isWifiNetWork(){
return isWifiConnected;
}
public boolean isMobileNetWork(){
return isMobileConnected;
}
/**
* 根據當前網路的狀態來設定網路連線的TYPE
* */
private void setMobileType(){
networkInfo = cm.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE){
isMobileConnected = true;
}else if(networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI){
isWifiConnected = true;
}else{
isWifiConnected = false;
isMobileConnected = false;
}
}
/**
* 取消廣播的註冊
* */
public void unRegisterNetWorkChangedReceiver(){
mContext.unregisterReceiver(mNetWorkChangedReceiver);
}
/**
* 接收網路連線發生改變的廣播:android.net.conn.CONNECTIVITY_CHANGE
* */
public class NetWorkChangedReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
setMobileType();
}
}<span style="font-family: 微軟雅黑; widows: auto; background-color: inherit;"> </span><span style="font-family: 微軟雅黑; widows: auto; background-color: inherit;"> </span>
3)非同步執行網路操作:因為在主執行緒執行網路操作,如果網路操作執行的時間稍長,就可能導致UI主執行緒執行緒ANR,這裡以Async Task來非同步執行網路操作:
...
private static final String url = http://www.weather.com.cn/data/sk/101010100.html;
private NetConnectMananger ncm;
...
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_start_http:
if(ncm.isMobileNetWork() || ncm.isWifiNetWork()){
new DownLoadTask().execute(url);
}else{
Toast.makeText(getApplicationContext(), "請確認網路是否連線!", Toast.LENGTH_LONG).show();
}
break;
default:
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//取消ncm中註冊的廣播。
ncm.unRegisterNetWorkChangedReceiver();
}
private class DownLoadTask extends AsyncTask<String, Void, String>{
@Override
protected String doInBackground(String... url) {
if(url != null){
try {
return downLoadData(url[0]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(String result) {
mTextView.setText(result);
}
public String downLoadData(String url) throws IOException{
InputStream stream = null;
int len = 500;
if(url == null){
Toast.makeText(getApplicationContext(), "無效網址!", Toast.LENGTH_LONG).show();
return null;
}
URL mUrl = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) mUrl.openConnection();
try{
urlConnection.setReadTimeout(1000);
urlConnection.setConnectTimeout(20000);
urlConnection.setRequestMethod("GET");
urlConnection.setDoInput(true);
urlConnection.connect();
int response = urlConnection.getResponseCode();
Log.i(TAG, "The response is: " + response);
stream = urlConnection.getInputStream();
String dataString = getStringFromStream(stream, len);
return dataString;
}finally{
if(stream != null){
stream.close();
}
if(urlConnection != null){
urlConnection.disconnect();
}
}
}
public String getStringFromStream(InputStream in, int len) throws UnsupportedEncodingException, IOException{
Reader reader = null;
reader = new InputStreamReader(in, "UTF-8");
char[] buffer = new char[len];
reader.read(buffer);
return new String(buffer);
}
}
參考:http://developer.android.com/training/basics/network-ops/connecting.html http://developer.android.com/reference/java/net/HttpURLConnection.html http://developer.android.com/training/basics/network-ops/managing.html