請改參考
2023.03.19
感覺這篇筆記的做法多做了一些不必要的事情,但這也是學習的歷程,所以還是保留......
ConnectivityManager
NetworkInfo
Process
ping(8) - Linux man page
或可透過 是否成功獲取網頁內容 做為判斷網際網路連線的依據,參考
【Kotlin】以 OkHttp3 偵測是否有網際網路連線能力
首先授予 app 權限
AndroidManifest.xml:
activity_main.xml:
一般偵測區域網路連線,只要 ConnectivityManager + NetworkInfo 即可,如下:
但這不足以得知是否連上網際網路,例如:
一般我們家裡都有無線路由器,當我們把路由器上 WAN 的線拔掉,家裡對外就斷線了,但 Android 設備仍可以連上路由器,則
info.isAvailable() 是 true
info.isConnected() 是 true
這樣無法判斷是否連上網際網路。
Android 的底層是 Linux,一般來說,在 /system/bin/ 下有 ping 這個程式,如果沒有,可能是被該 Android 裝置的製造商移除了;因為是 Linux 的指令,指令參數請參考 Linux;我們可以藉 ping 來偵測網路是否通。
如果網際網路是通的,則 strPing 字串會含有如下的內容:
64 bytes from 168.95.1.1: icmp_seq=1 ttl=249 time=4.67 ms
64 bytes from 168.95.1.1: icmp_seq=2 ttl=249 time=6.55 ms
64 bytes from 168.95.1.1: icmp_seq=3 ttl=249 time=4.29 ms
64 bytes from 168.95.1.1: icmp_seq=4 ttl=249 time=5.27 ms
提醒您:老人家這篇筆記偷懶,並未考慮 app 執行的程式合理性及最佳化,ping 這種耗時的指令,建議您還是放在 Thread 或 AsyncTask 執行比較好。
相關筆記 ----
【Android】AsyncTask - Thread 外的另一選擇
AndroidManifest.xml:
- ...
- ...
- <uses-permission android:name="android.permission.INTERNET"/>
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- ...
- ...
activity_main.xml:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context="com.oldgrayduck.ping.MainActivity">
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="PING"
- android:id="@+id/btnPing"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:nestedScrollingEnabled="true"
- android:onClick="onbtnPingClicked"/>
- </RelativeLayout>
一般偵測區域網路連線,只要 ConnectivityManager + NetworkInfo 即可,如下:
- ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo info = connManager.getActiveNetworkInfo();
- // 可透過下列指令取得進一步的連線資訊
- info.getTypeName(); // 目前以何種方式連線 (WIFI, MOBILE)
- info.getState(); // 目前連線狀態 (DISCONNECTED, CONNECTING, CONNECTED)
- info.isAvailable(); // 目前網路是否可使用 (true/false)
- info.isConnected(); // 網路是否已連接 (true/false)
- info.isConnectedOrConnecting(); // 網路是否已連接 或 連線中 (true/false)
- info.isFailover(); // 網路目前是否有問題 (true/false)
- info.isRoaming(); // 網路目前是否在漫遊中 (true/false)
但這不足以得知是否連上網際網路,例如:
一般我們家裡都有無線路由器,當我們把路由器上 WAN 的線拔掉,家裡對外就斷線了,但 Android 設備仍可以連上路由器,則
info.isAvailable() 是 true
info.isConnected() 是 true
這樣無法判斷是否連上網際網路。
Android 的底層是 Linux,一般來說,在 /system/bin/ 下有 ping 這個程式,如果沒有,可能是被該 Android 裝置的製造商移除了;因為是 Linux 的指令,指令參數請參考 Linux;我們可以藉 ping 來偵測網路是否通。
- ...
- ...
- public void onbtnPingClicked(View v)
- {
- if (isConnected())
- Toast.makeText(this, "網路已連線", Toast.LENGTH_LONG).show();
- else
- Toast.makeText(this, "斷線中", Toast.LENGTH_LONG).show();
- }
- private boolean isConnected()
- {
- boolean result = false;
- ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo info = connManager.getActiveNetworkInfo();
- if (info==null || !info.isConnected())
- {
- Log.d(TAG, "網路 不通");
- result = false;
- }
- else
- {
- if(info.isConnected())
- Log.d(TAG, "info connected");
- else
- Log.d(TAG, "info disconnected");
- if (info.isAvailable())
- {
- try
- {
- Log.d(TAG, "info is available");
- // 不像 Windows 的 ping 預設執行 4 次
- // Linux 的 ping 預設是一直執行的,所以一定要下參數指定次數
- // 不然會造成您的 app 無回應
- // 試著 ping 168.95.1.1, 4 次, 參數 -c 4
- Process process = new ProcessBuilder().command("/system/bin/ping","-c 4","168.95.1.1")
- .redirectErrorStream(true)
- .start();
- try
- {
- String strPing = "";
- InputStream in = process.getInputStream();
- OutputStream out = process.getOutputStream();
- InputStreamReader reader = new InputStreamReader(in, "utf-8");
- int i;
- Log.d(TAG, "read instream");
- while ((i = in.read()) != -1)
- {
- strPing = strPing + (char) i;
- }
- out.close();
- in.close();
- reader.close();
- Log.d(TAG, "strPing ==== "+strPing);
- if(strPing.indexOf("ttl")>=0)
- {
- Log.d(TAG, "strPing 字串中有 ttl");
- result = true;
- }
- else
- {
- Log.d(TAG, "Ping 沒回應");
- result = false;
- }
- }
- catch(Exception e)
- {
- result = false;
- }
- finally
- {
- // 記得要釋放掉 process
- process.destroy();
- }
- }
- catch (Exception e)
- {
- Log.d(TAG, "Exception--> " + e.getMessage());
- result = false;
- }
- }
- else
- {
- Log.d(TAG, "網路不可用");
- result = false;
- }
- }
- return result;
- }
- ...
- ...
如果網際網路是通的,則 strPing 字串會含有如下的內容:
64 bytes from 168.95.1.1: icmp_seq=1 ttl=249 time=4.67 ms
64 bytes from 168.95.1.1: icmp_seq=2 ttl=249 time=6.55 ms
64 bytes from 168.95.1.1: icmp_seq=3 ttl=249 time=4.29 ms
64 bytes from 168.95.1.1: icmp_seq=4 ttl=249 time=5.27 ms
提醒您:老人家這篇筆記偷懶,並未考慮 app 執行的程式合理性及最佳化,ping 這種耗時的指令,建議您還是放在 Thread 或 AsyncTask 執行比較好。
相關筆記 ----
【Android】AsyncTask - Thread 外的另一選擇
沒有留言:
張貼留言