1. 程式人生 > >Android 網路請求及網路狀態判斷

Android 網路請求及網路狀態判斷

文章轉載:

網址:http://blog.csdn.net/anye_anye/article/details/50569114

Android 中判斷網路連線是否可用

一、判斷網路連線是否可用

public static boolean isNetworkAvailable(Context context) {   
    ConnectivityManager cm = (ConnectivityManager) context   
            .getSystemService(Context.CONNECTIVITY_SERVICE);   
    if (cm == null) {   
    } else {
       //如果僅僅是用來判斷網路連線
        //則可以使用 cm.getActiveNetworkInfo().isAvailable();  
        NetworkInfo[] info = cm.getAllNetworkInfo();   
        if (info != null) {   
            for (int i = 0; i < info.length; i++) {   
                if (info[i].getState() == NetworkInfo.State.CONNECTED) {   
                    return true;   
                }   
            }   
        }   
    }   
    return false;   
   } 

二、判斷GPS是否開啟

public static boolean isGpsEnabled(Context context) {   
    LocationManager lm = ((LocationManager) context   
            .getSystemService(Context.LOCATION_SERVICE));   
    List<String> accessibleProviders = lm.getProviders(true);   
    return accessibleProviders != null && accessibleProviders.size() > 0;   
}

三、判斷WIFI是否開啟

public static boolean isWifiEnabled(Context context) {   
    ConnectivityManager mgrConn = (ConnectivityManager) context   
            .getSystemService(Context.CONNECTIVITY_SERVICE);   
    TelephonyManager mgrTel = (TelephonyManager) context   
            .getSystemService(Context.TELEPHONY_SERVICE);   
    return ((mgrConn.getActiveNetworkInfo() != null && mgrConn   
            .getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) || mgrTel   
            .getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS);   
}

四、判斷是否是3G網路

public static boolean is3rd(Context context) {   
    ConnectivityManager cm = (ConnectivityManager) context   
            .getSystemService(Context.CONNECTIVITY_SERVICE);   
    NetworkInfo networkINfo = cm.getActiveNetworkInfo();   
    if (networkINfo != null   
            && networkINfo.getType() == ConnectivityManager.TYPE_MOBILE) {   
        return true;   
    }   
    return false;   
}

五、判斷是wifi還是3g網路,使用者的體現性在這裡了,wifi就可以建議下載或者線上播放。

 public static boolean isWifi(Context context) {   
        ConnectivityManager cm = (ConnectivityManager) context   
                .getSystemService(Context.CONNECTIVITY_SERVICE);   
        NetworkInfo networkINfo = cm.getActiveNetworkInfo();   
        if (networkINfo != null   
                && networkINfo.getType() == ConnectivityManager.TYPE_WIFI) {   
            return true;   
        }   
        return false;   
    }

Android開發請求網路方式詳解

  現在就簡單的介紹一下Android常用的聯網方式,包括JDK支援的HttpUrlConnection,Apache支援的HttpClient,以及開源的一些聯網框架(譬如AsyncHttpClient)的介紹。本篇部落格只講實現過程和方式,不講解原理,否則原理用文字很難以講清,其實我們知道怎麼去用,就可以解決一些基本開發需要了。 
  絕大多數的Android應用聯網都是基於Http協議的,也有很少是基於Socket的,我們這裡主要講解基於Http協議的聯網方式。講解例項是建立在一個模擬的登入小模組中進行,登入請求資料僅僅只有username和password兩個簡單欄位。

HttpUrlConnection

HttpUrlConnection是JDK裡提供的聯網API,我們知道Android SDK是基於Java的,所以當然優先考慮HttpUrlConnection這種最原始最基本的API,其實大多數開源的聯網框架基本上也是基於JDK的HttpUrlConnection進行的封裝罷了,掌握HttpUrlConnection需要以下幾個步驟:

1、將訪問的路徑轉換成URL。

URL url = new URL(path);

2、通過URL獲取連線。

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

3、設定請求方式。

conn.setRequestMethod(GET);

4、設定連線超時時間。

conn.setConnectTimeout(5000);

5、設定請求頭的資訊。

conn.setRequestProperty(User-Agent, Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0));

6、獲取響應碼

int code = conn.getResponseCode();

7、針對不同的響應碼,做不同的操作

7.1、請求碼200,表明請求成功,獲取返回內容的輸入流

InputStream is = conn.getInputStream();

7.2、將輸入流轉換成字串資訊

public class StreamTools {
/**
 * 將輸入流轉換成字串
 * 
 * @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.e(tag, e.toString());
        return null;
    }
}
}

7.3、若返回值400,則是返回網路異常,做出響應的處理。

HttpUrlConnection傳送GET請求

/**
 * 通過HttpUrlConnection傳送GET請求
 * 
 * @param username
 * @param password
 * @return
 */
public static String loginByGet(String username, String password) {
    String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username= + username + &password= + password;
    try {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5000);
        conn.setRequestMethod(GET);
        int code = conn.getResponseCode();
        if (code == 200) {
            InputStream is = conn.getInputStream(); // 位元組流轉換成字串
            return StreamTools.streamToString(is);
        } else {
            return 網路訪問失敗;
        }
    } catch (Exception e) {
        e.printStackTrace();
        return 網路訪問失敗;
    }
}

HttpUrlConnection傳送POST請求

/**
 * 通過HttpUrlConnection傳送POST請求
 * 
 * @param username
 * @param password
 * @return
 */
public static String loginByPost(String username, String password) {
    String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
    try {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(5000);
        conn.setRequestMethod(POST);
        conn.setRequestProperty(Content-Type, application/x-www-form-urlencoded);
        String data = username= + username + &password= + password;
        conn.setRequestProperty(Content-Length, data.length() + );
        // POST方式,其實就是瀏覽器把資料寫給伺服器
        conn.setDoOutput(true); // 設定可輸出流
        OutputStream os = conn.getOutputStream(); // 獲取輸出流
        os.write(data.getBytes()); // 將資料寫給伺服器
        int code = conn.getResponseCode();
        if (code == 200) {
            InputStream is = conn.getInputStream();
            return StreamTools.streamToString(is);
        } else {
            return 網路訪問失敗;
        }
    } catch (Exception e) {
        e.printStackTrace();
        return 網路訪問失敗;
    }
}

HttpClient

  HttpClient是開源組織Apache提供的Java請求網路框架,其最早是為了方便Java伺服器開發而誕生的,是對JDK中的HttpUrlConnection各API進行了封裝和簡化,提高了效能並且降低了呼叫API的繁瑣。 
  Android因此也引進了這個聯網框架,我們再不需要匯入任何jar或者類庫就可以直接使用,值得注意的是Android官方已經宣佈不建議使用HttpClient了,我們再開發的時候儘量少用吧,但是用了也無妨!

HttpClient傳送GET請求

1, 建立HttpClient物件

2,建立HttpGet物件,指定請求地址(帶引數)

3,使用HttpClient的execute(),方法執行HttpGet請求,得到HttpResponse物件

4,呼叫HttpResponse的getStatusLine().getStatusCode()方法得到響應碼

5,呼叫的HttpResponse的getEntity().getContent()得到輸入流,獲取服務端寫回的資料

/**
 * 通過HttpClient傳送GET請求
 * 
 * @param username
 * @param password
 * @return
 */
public static String loginByHttpClientGet(String username, String password) {
    String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=
            + username + &password= + password;
    HttpClient client = new DefaultHttpClient(); // 開啟網路訪問客戶端
    HttpGet httpGet = new HttpGet(path); // 包裝一個GET請求
    try {
        HttpResponse response = client.execute(httpGet); // 客戶端執行請求
        int code = response.getStatusLine().getStatusCode(); // 獲取響應碼
        if (code == 200) {
            InputStream is = response.getEntity().getContent(); // 獲取實體內容
            String result = StreamTools.streamToString(is); // 位元組流轉字串
            return result;
        } else {
            return 網路訪問失敗;
        }
    } catch (Exception e) {
        e.printStackTrace();
        return 網路訪問失敗;
    }
}

HttpClient傳送POST請求

1,建立HttpClient物件

2,建立HttpPost物件,指定請求地址

3,建立List,用來裝載引數

4,呼叫HttpPost物件的setEntity()方法,裝入一個UrlEncodedFormEntity物件,攜帶之前封裝好的引數

5,使用HttpClient的execute()方法執行HttpPost請求,得到HttpResponse物件

6, 呼叫HttpResponse的getStatusLine().getStatusCode()方法得到響應碼

7, 呼叫的HttpResponse的getEntity().getContent()得到輸入流,獲取服務端寫回的資料

/**
 * 通過HttpClient傳送POST請求
 * 
 * @param username
 * @param password
 * @return
 */
public static String loginByHttpClientPOST(String username, String password) {
    String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
    try {
        HttpClient client = new DefaultHttpClient(); // 建立一個客戶端
        HttpPost httpPost = new HttpPost(path); // 包裝POST請求
        // 設定傳送的實體引數
        List<namevaluepair> parameters = new ArrayList<namevaluepair>();
        parameters.add(new BasicNameValuePair(username, username));
        parameters.add(new BasicNameValuePair(password, password));
        httpPost.setEntity(new UrlEncodedFormEntity(parameters, UTF-8));
        HttpResponse response = client.execute(httpPost); // 執行POST請求
        int code = response.getStatusLine().getStatusCode();
        if (code == 200) {
            InputStream is = response.getEntity().getContent();
            String result = StreamTools.streamToString(is);
            return result;
        } else {
            return 網路訪問失敗;
        }
    } catch (Exception e) {
        e.printStackTrace();
        return 訪問網路失敗;
    }
}

開源聯網框架

1、AsyncHttpClient

除了上述Android官方推薦的聯網框架以外,在開源世界裡關於聯網框架真是太多太多了,例如afinal,xutils等等,都是一些開源大牛自己封裝的聯網框架,並且在GitHub開源社群中可以下載到,其實類似的開源聯網框架基本上也是基於HttpUrlConnection的進一步封裝,大大提高了效能,同時更加簡化了使用方法,這裡先介紹AsyncHttpClient的一些使用方法。 AsyncHttpClient是一個非常優秀的聯網框架,不僅支援所有Http請求的方式,而且還支援檔案的上傳和下載,要知道用HttpUrlConnection寫一個檔案上傳和下載健全功能是很需要花費一定時間和精力的,因為請求頭實在是太多了,稍有不慎就會寫錯。但是AsyncHttpClient已經封裝好了這些“麻煩”,我們只需要下載到AsyncHttpClient的jar包或者原始碼匯入專案中,Http,上傳,下載等等,只需要幾個簡單的api即可搞定。 AsyncHttpClient的GitHub主頁:https://github.com/AsyncHttpClient/async-http-client/

AsyncHttpClient傳送GET請求

1,將下載好的原始碼拷貝到src目錄下

2,建立一個AsyncHttpClient的物件

3,呼叫該類的get方法傳送GET請求,傳入請求資源地址URL,建立AsyncHttpResponseHandler物件

4,重寫AsyncHttpResponseHandler下的兩個方法,onSuccess和onFailure方法

/**
 * 通過AsyncHttpClient傳送GET請求
 */
public void loginByAsyncHttpGet() {
    String path = http://192.168.0.107:8080/WebTest/LoginServerlet?username=zhangsan&password=123;
    AsyncHttpClient client = new AsyncHttpClient();
    client.get(path, new AsyncHttpResponseHandler() {

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            // TODO Auto-generated method stub
            Log.i(TAG, 請求失敗: + new String(arg2));
        }

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            // TODO Auto-generated method stub
            Log.i(TAG, 請求成功: + new String(arg2));
        }
    });
}

AsyncHttpClient傳送POST請求

1,將下載好的原始碼拷貝到src目錄下

2,建立一個AsyncHttpClient的物件

3,建立請求引數,RequestParams物件

4,呼叫該類的post方法發POST,傳入請求資源地址URL,請求引數RequestParams,建立AsyncHttpResponseHandler物件

5,重寫AsyncHttpResponseHandler下的兩個方法,onSuccess和onFailure方法

/**
 * 通過AsyncHttpClient傳送POST請求
 */
public void loginByAsyncHttpPost() {
    String path = http://192.168.0.107:8080/WebTest/LoginServerlet;
    AsyncHttpClient client = new AsyncHttpClient();
    RequestParams params = new RequestParams();
    params.put(username, zhangsan);
    params.put(password, 123);
    client.post(path, params, new AsyncHttpResponseHandler() {

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            // TODO Auto-generated method stub
            Log.i(TAG, 請求失敗: + new String(arg2));
        }

        @Override
        public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
            // TODO Auto-generated method stub
            Log.i(TAG, 請求成功: + new String(arg2));
        }
    });

AsyncHttpClient上傳檔案

1,將下載好的原始碼拷貝到src目錄下

2,建立一個AsyncHttpClient的物件

3,建立請求引數,RequestParams物件,請求引數僅僅包含檔案物件即可,例如:

params.put(profile_picture, new File(/sdcard/pictures/pic.jpg));

4,呼叫該類的post方法發POST,傳入請求資源地址URL,請求引數RequestParams,建立AsyncHttpResponseHandler物件

5,重寫AsyncHttpResponseHandler下的兩個方法,onSuccess和onFailure方法

2、Android Volley框架使用詳解

  Volley是一個由Google官方推出的網路通訊庫,它使得Android進行網路請求時更加方便、快速、健壯,同時對網路圖片載入也提供了良好的支援。

1、獲取volley原始碼

2、使用例項

  使用Volley必須在AndroidManifest.xml中新增 android.permission.INTERNET許可權,使用Volley時Google建議建立volley單例工具類

public class VolleySingleton {
private static VolleySingleton volleySingleton;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private Context mContext;
public VolleySingleton(Context context) {
    this.mContext = context;
    mRequestQueue = getRequestQueue();
    mImageLoader = new ImageLoader(mRequestQueue,
    new ImageLoader.ImageCache(){
        private final LruCache<String,Bitmap> cache = new LruCache<String ,Bitmap>(20);
        @Override
        public Bitmap getBitmap(String url){
            return cache.get(url);
        }
        @Override
        public void putBitmap(String url,Bitmap bitmap){
            cache.put(url,bitmap);
        }
    });
}
public static synchronized VolleySingleton getVolleySingleton(Context context){
    if(volleySingleton == null){
        volleySingleton = new VolleySingleton(context);
    }
    return volleySingleton;
}
public RequestQueue getRequestQueue(){
    if(mRequestQueue == null){
        mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext());
    }
    return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req){
    getRequestQueue().add(req);
}
public ImageLoader getImageLoader() {
    return mImageLoader;
}
}

  首先使用 Volley.newRequestQueue獲取 RequestQueue物件

RequestQueue mRequestQueue = VolleySingleton.getVolleySingleton(this.getApplicationContext()).getRequestQueue();

  RequestQueue是請求佇列物件,它可以快取所有的HTTP網路請求,然後按照其內部演算法併發的傳送這些網路請求,它能夠很好的支撐高併發請求,不要每個請求都建立RequestQueue物件,建立多個RequestQueue會耗費資源

  傳送StringRequest請求

StringRequest stringRequest = new StringRequest(Request.Method.GET,"https://www.baidu.com",new Listener<String>(){

        @Override
        public void onResponse(String s) {
            //列印請求返回結果
            Log.e("volley",s);
        }
    },new ErrorListener(){
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            Log.e("volleyerror","erro2");
        }
    });
//將StringRequest物件新增進RequestQueue請求佇列中
   VolleySingleton.getVolleySingleton(this.getApplicationContext()).addToRequestQueue(stringRequest);

  到此已經完成了StringRequest請求。StringRequest提供了兩個構造方法

public StringRequest(java.lang.String url, com.android.volley.Response.Listener<java.lang.String> listener, com.android.volley.Response.ErrorListener errorListener);

public StringRequest(int method, java.lang.String url, com.android.volley.Response.Listener<java.lang.String> listener, com.android.volley.Response.ErrorListener errorListener);

  引數method是HTTP的請求型別,通常有GET和POST兩種;引數url是請求地址;引數listener是伺服器響應成功的回撥,引數errorListener是伺服器響應失敗的回撥。如果想通過POST方式請求並攜帶引數,遺憾的是StringRequest並沒有提供帶引數請求,但是當傳送POST請求時,Volley會呼叫StringRequest的父類Request的getParams()方法來獲取POST引數,所以我們只要使用StringRequest匿名類重寫getParams()方法將引數傳遞進去就可以實現帶引數的StringRequest請求。

StringRequest stringRequest = new StringRequest(Method.POST, url,  listener, errorListener) {  
@Override  
protected Map<String, String> getParams() throws AuthFailureError {  
    Map<String, String> map = new HashMap<String, String>();  
    map.put("params1", "value1");  
    map.put("params2", "value2");  
    return map;  
}  
}; 

傳送JsonObjectRequest請求

JsonObjectRequest jr = new JsonObjectRequest(Request.Method.GET,url,null,new Response.Listener<JSONObject>(){
        @Override
        public void onResponse(JSONObject jsonObject) {
            Log.e("volley",jsonObject.toString());
        }
    },new ErrorListener(){
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            Log.e("volleyerror","erro");
        }
    });
 VolleySingleton.getVolleySingleton(this.getApplicationContext()).addToRequestQueue(jr);

JsonObjectRequest的構造方法引數和StringRequest一致,不在此累贅。

使用ImageRequest載入圖片

ImageView mImageView;
String url = "http://i.imgur.com/7spzG.png";
mImageView = (ImageView) findViewById(R.id.myImage);
ImageRequest request = new ImageRequest(url,
new Response.Listener<Bitmap>() {
    @Override
    public void onResponse(Bitmap bitmap) {
        mImageView.setImageBitmap(bitmap);
    }
}, 0, 0, Config.RGB_565,
new Response.ErrorListener() {
    public void onErrorResponse(VolleyError error) {
        mImageView.setImageResource(R.drawable.image_load_error);
    }
});
VolleySingleton.getVolleySingleton(this.getApplicationContext()).addToRequestQueue(request);

ImageRequest的建構函式

public ImageRequest(java.lang.String url, com.android.volley.Response.Listener<android.graphics.Bitmap> listener, int maxWidth, int maxHeight, android.graphics.Bitmap.Config decodeConfig, com.android.volley.Response.ErrorListener errorListener) { /* compiled code */ }

  引數url是圖片地址,引數listener是請求響應成功回撥,引數maxWidth是圖片最大寬度,引數maxHeight是圖片最大高度,如果指定的網路圖片的寬度或高度大於這裡的最大值,則會對圖片進行壓縮,指定成0的話就表示不管圖片有多大,都不會進行壓縮。引數decodeConfig是圖片的顏色屬性,其值是Bitmap.Config類的幾個常量,引數errorListener是請求響應失敗回撥

使用 ImageLoader 載入圖片

ImageLoader mImageLoader;
ImageView mImageView;
private static final String IMAGE_URL =
"http://developer.android.com/images/training/system-ui.png";
mImageView = (ImageView) findViewById(R.id.regularImageView);
mImageLoader = VolleySingleton.getVolleySingleton(this.getApplicationContext()).getImageLoader();
//IMAGE_URL是圖片網路地址
//mImageView是ImageView例項
//R.drawable.def_image預設圖片id
//R.drawable.err_image載入圖片錯誤時的圖片
mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView,
     R.drawable.def_image, R.drawable.err_image));

使用NetworkImageView載入圖片

XML佈局檔案

<com.android.volley.toolbox.NetworkImageView
    android:id="@+id/networkImageView"
    android:layout_width="150dp"
    android:layout_height="170dp"
    android:layout_centerHorizontal="true" />

程式碼

ImageLoader mImageLoader;
NetworkImageView mNetworkImageView;
private static final String IMAGE_URL =
"http://developer.android.com/images/training/system-ui.png";
mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);
mImageLoader = VolleySingleton.getVolleySingleton(this.getApplicationContext()).getImageLoader();
mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader);

  我們可以呼叫它的setDefaultImageResId()方法、setErrorImageResId()方法和setImageUrl()方法來分別設定載入中顯示的圖片,載入失敗時顯示的圖片

取消網路請求

  Volley還提供了取消網路請求的方法並且可以聯動Activity的生命週期,比如在Activity的onStop()方法中呼叫cance()方法取消網路請求。

public static final String TAG = "MyTag";
StringRequest stringRequest; // Assume this exists.
RequestQueue mRequestQueue;  // Assume this exists.

// Set the tag on the request.
stringRequest.setTag(TAG);

// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);

Activity的onStop()方法

@Override
protected void onStop () {
super.onStop();
if (mRequestQueue != null) {
    mRequestQueue.cancelAll(TAG);
}
}