Android功能點(一)——判斷網絡是否真正連通

我們知道,當手機上顯示網絡連接成功時,并不一定可以真的上網。常見的情況是,連上路由后需要進行跳轉登錄,或者干脆路由連接到網絡的端口壞掉。因此在進行網絡通訊前,可能需要確認網絡是否真正聯通。

經典方法


一種常用的方法,也是沿用pc機上查看網絡是否聯通的方法,就是使用ping命令。要注意ping在windows上和linux上的參數意義是不一樣的。使用-c來確定ping的次數。adb shell進入android環境,輸入命令,效果如下。這里www.a.shifen.com是百度為了防止攻擊而設置的殼地址,可以忽略。

shell環境中的ping

那么現在要做的就是在android代碼里使用ping命令,代碼如下:

Runtime runtime = Runtime.getRuntime();
                  try {
                    Process p = runtime.exec("ping -c 3 www.baidu.com");
                    int ret = p.waitFor();
                    Log.i("Avalible", "Process:"+ret);
                } catch (Exception e) {
                    e.printStackTrace();
                }

然后我們來看下不同網絡狀態下代碼的執行效果:

  • 連通的移動數據網絡下:
連通的移動數據網絡下
  • 在需要網頁認證的wifi下:
在需要網頁認證的wifi下
  • 在wifi打開但沒有網絡連接,數據也不可用的狀態下:
在wifi打開但沒有網絡連接,數據也不可用的狀態下
  • 在不可用wifi下:
在不可用wifi下
  • 在可用wifi下:
在可用wifi下

基本上只要判斷是否是0即可,若是0則網絡真正可用

Android 6.0以上可用方法


在API 21增加了一個類NetworkCapabilities,其中有很多對于網絡性能的描述,可以通過ConnectivityManager獲得描述當前網絡的NetworkCapabilities。而在API23中,增加了一個描述NET_CAPABILITY_VALIDATED。文檔中對其描述如下:

Indicates that connectivity on this network was successfully validated. For example, for a network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully detected.

實驗表明,當NetworkCapabilities的描述中有VALIDATED這個描述時,此網絡是真正可用的。使用如下代碼獲得當前網絡的capabilities:

NetworkCapabilities networkCapabilities = mConnectivityManager.getNetworkCapabilities(mConnectivityManager.getActiveNetwork());
Log.i("Avalible", "NetworkCapalbilities:"+networkCapabilities.toString());

可以看到代碼非常簡單,將對于NetworkCapabilities的描述打印出來,不同網絡狀態下結果如下:

  • 在可聯通的wifi下,可看到出現了VALIDATED的標記:
在可聯通的wifi下
  • 在需要認證的wifi下,可以看到相應區域沒有VALIDATED的標記:
在需要認證的wifi下
  • 在不可上網的wifi下,可以看到也沒有VALIDATED的標記:
在不可上網的wifi下
  • 在移動數據下,可以看到VALIDATED又出現了:
在移動數據下

因此可以通過判斷這個標記是否存在來判斷網絡的連通性。通過如下調用來判斷標記存在與否:

networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);

可惜只能6.0以上使用,目前還是又很多6.0下的手機在使用的,因此經典方法還是很重要。

http協議


其實查看網絡連接是否成功的本質,就是實際去連下,看看能不能連到。所以理論上任何網絡通訊協議都可以來處理這件事。但實際上,開發中大多使用經典方法是有道理的。因為ping命令本身就是為了查看網絡連通狀況而存在。而使用http協議的話,不但數據包會較大、使用較復雜,很多情況也沒法處理。下面來簡單地用Get去訪問url看看會發生什么。代碼如下:

HttpURLConnection httpConn = null;
                InputStream inputStream = null;
                int respondcode = -1;
                try{
                    URL url = new URL("http://www.baidu.com");
                    httpConn = (HttpURLConnection)url.openConnection();
                    httpConn.setRequestMethod("GET");
                    respondcode = httpConn.getResponseCode();
                    Log.i("Avalible", "HttpURLConnection1:"+respondcode+" "+httpConn.getHeaderField("Location"));
                    url = new URL(httpConn.getHeaderField("Location"));
                    httpConn = (HttpURLConnection)url.openConnection();
                    httpConn.setUseCaches(false);
                    httpConn.setRequestMethod("GET");
                    respondcode = httpConn.getResponseCode();
                    Log.i("Avalible", "HttpURLConnection2:"+respondcode+" "+httpConn.getHeaderField("Location"));
                }catch(Exception e){
                    e.printStackTrace();

                }

由于可能會發生重定向,因此進行兩次http請求,并且將重定向的url打印出來查看。不同網絡下結果如下:

  • 移動數據流量。首先進行了一次跳轉,第二次返回200成功:
移動數據流量
  • 可連通wifi下,完全一樣:
可連通wifi下
  • 需要認證wifi下,返回200,但實際上并沒有確認可連通www.baidu.com,只是連接到了需要登錄的地址。因此實際上是沒法通過返回值來判斷究竟能否上網的:
需要認證wifi下
  • 而在無法上網的情況下,是直接報錯的:
無法上網的情況下

因此相對來說,使用http協議,處理的過程更加復雜,返回結果不夠明確,相對不適合用來判斷網絡是否連通

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,813評論 25 708
  • 0 01、網絡管理的五大功能(包括每項功能的具體情況) 1.配置管理:ISO定義的管理功能域中,配置管理包括視圖管...
    哈熝少主閱讀 3,138評論 1 20
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,180評論 4 61
  • 三六九, 出門走, 一別父母有鄉愁。 兒千里, 母擔憂, 隨心相伴到永久。
    橘子洲的魚閱讀 417評論 2 2