一、查看當前手機的網(wǎng)絡狀態(tài),需要獲取ConnectionManager
- ConnectionManager方式
/**
* 判斷當前是否有網(wǎng)絡連接,但是如果該連接的網(wǎng)絡無法上網(wǎng),也會返回true
* @param mContext
* @return
*/
public static boolean isNetConnection(Context mContext) {
if (mContext!=null){
ConnectivityManager connectivityManager =
(ConnectivityManager) mContext.
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
boolean connected = networkInfo.isConnected();
if (networkInfo!=null&&connected){
if (networkInfo.getState()== NetworkInfo.State.CONNECTED){
return true;
}else{
return false;
}
}
}
return false;
}
- NetworkCapabilities類方式(6.0以上)
NetworkCapabilities是API 21新增加的一個工具類,這類本身沒有太多內容,主要是用來描述網(wǎng)絡狀態(tài)和傳輸類型,具體的內容請查閱相關文檔,這里就不多介紹了。NetworkCapabilities提供了方法,用來判斷當前網(wǎng)絡是否可用,而且是不耗時的方法。
/**
* 判斷當前網(wǎng)絡是否可用(6.0以上版本)
* 實時
* @param context
* @return
*/
public static boolean isNetSystemUsable(Context context) {
boolean isNetUsable = false;
ConnectivityManager manager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
NetworkCapabilities networkCapabilities =
manager.getNetworkCapabilities(manager.getActiveNetwork());
if (networkCapabilities != null) {
isNetUsable = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}
}
return isNetUsable;
}
二、有網(wǎng)絡連接情況下,檢測網(wǎng)絡能否正常上網(wǎng)
注意:此方法需要在子線程調用,否則報錯:android.os.NetworkOnMainThreadException
/**
* 功能:檢測當前URL是否可連接或是否有效,
* 描述:最多連接網(wǎng)絡 x次, 如果 x 次都不成功,視為該地址不可用
* @return true是可以上網(wǎng),false是不能上網(wǎng)
*/
private static URL url;
private static HttpURLConnection con;
private static int state = -1;
public static boolean isNetOnline() {
// Android 4.0 之后不能在主線程中請求HTTP請求
int counts = 0;
boolean isNetsOnline = true;
while (counts < 2) {
try {
url = new URL("https://www.baidu.com");
con = (HttpURLConnection) url.openConnection();
state = con.getResponseCode();
Log.e("FragmentNet", "isNetOnline counts: " + counts + "=state: " + state);
if (state == 200) {
isNetsOnline = true;
}
break;
} catch (Exception ex) {
isNetsOnline = false;
counts++;
Log.e("FragmentNet", "isNetOnline URL不可用,連接第 " + counts + " 次");
continue;
}
}
return isNetsOnline;
}
三、ping 網(wǎng)絡方式
注意: ping網(wǎng)址是最最常用的一種判斷網(wǎng)絡的方式,也是通用方法。這種方法最大的劣勢是,耗時很長,我曾計算過,ping一次的時間大約是10s,兩次是11s,每增加一次就多耗時1s。雖然這種方法耗時較長,但這是目前最常用的方法,而且沒有更好的方法取代。
有時候我們連接上一個沒有外網(wǎng)連接的WiFi或者有線就會出現(xiàn)這種極端的情況,
目前Android SDK還不能識別這種情況,一般的解決辦法就是ping一個外網(wǎng)
/**
* @category 判斷是否有外網(wǎng)連接(普通方法不能判斷外網(wǎng)的網(wǎng)絡是否連接,比如連接上局域網(wǎng))
* @return
*/
public static final boolean ping() {
String result = null;
try {
String ip = "www.baidu.com";// ping 的地址,可以換成任何一種可靠的外網(wǎng)
Process p = Runtime.getRuntime().exec("ping -c 3 -w 100 " + ip);// ping網(wǎng)址3次
// 讀取ping的內容,可以不加
InputStream input = p.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(input));
StringBuffer stringBuffer = new StringBuffer();
String content = "";
while ((content = in.readLine()) != null) {
stringBuffer.append(content);
}
// Log.d("------ping-----", "result content : " + stringBuffer.toString());
// ping的狀態(tài)
int status = p.waitFor();
if (status == 0) {
result = "success";
return true;
} else {
result = "failed";
}
} catch (IOException e) {
result = "IOException";
} catch (InterruptedException e) {
result = "InterruptedException";
} finally {
// Log.d("----result---", "result = " + result);
}
return false;
}
雖然現(xiàn)在主流手機系統(tǒng)都是6.0以上,但是總有一些“老爺機”還堅挺的使用5.0甚至是4.4以上的系統(tǒng)。為了適配問題,方法1依然是主流的方法,這也是Android開發(fā)最麻煩的地方。
另外,ping的方法可以判斷當前網(wǎng)絡的可用情況。
process.waitFor() 返回0,當前網(wǎng)絡可用
process.waitFor() 返回1,需要網(wǎng)頁認證的wifi
process.waitFor() 返回2,當前網(wǎng)絡不可用
-關于需要網(wǎng)頁認證的wifi:
警惕360wifi?。。?/code>
360wifi本身其實是不需要認證的,連接上網(wǎng)絡之后就可以直接使用。但是用方法進行判斷時,
process.waitFor()返回的卻是1。有一些手機系統(tǒng)(比如魅族),在監(jiān)測到當前wifi需要網(wǎng)頁認證時,
會自動打開瀏覽器。這本身是一個很人性化的設計,然而會被某些企業(yè)利用,在連接上wifi之后,
自動跳轉到廣告頁面。
所以大家如果用360wifi進行驗證,自求多福,那畢竟是360啊。
四、解決android.os.NetworkOnMainThreadException
1.在Android 4.0以上,網(wǎng)絡連接不能放在主線程上,不然就會報錯android.os.NetworkOnMainThreadException。但是4.0下版本可以不會報錯。
2.在Android4.0以后,會發(fā)現(xiàn),只要是寫在主線程(就是Activity)中的HTTP請求,運行時都會報錯,這是因為Android在4.0以后為了防止應用的ANR(Aplication Not Response)異常,Android這個設計是為了防止網(wǎng)絡請求時間過長而導致界面假死的情況發(fā)生。

解決此問題有兩種解決的方法:
1.可以再Activity的onCreate()方法中加入這樣一段代碼,適用于網(wǎng)絡請求數(shù)據(jù)量很小的話,如下
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
2.啟動一條子線程進行你的網(wǎng)絡請求,推薦使用這種
// Android 4.0 之后不能在主線程中請求HTTP請求
new Thread(new Runnable(){
@Override
public void run() {
cachedImage = asyncImageLoader.loadDrawable(imageUrl, position);
imageView.setImageDrawable(cachedImage);
}
}).start();