Android獲取網(wǎng)絡(luò)連接狀態(tài)新方法整理
一. 問題背景
Android12上,有的app模塊判斷當(dāng)前網(wǎng)絡(luò)的類型和連接狀態(tài)時(shí),還是使用的舊的API,導(dǎo)致返回的結(jié)果不準(zhǔn)確,影響代碼邏輯判斷,本篇文章就這一問題,整理一下判斷網(wǎng)絡(luò)類型和連接狀態(tài)的新方法。
二. 原因分析
在Android 10以前的版本,大家都是通過NetworkInfo.java 的getType()方法獲取網(wǎng)絡(luò)類型,通過isConnected()方法來判斷是否連接上, 判斷網(wǎng)絡(luò)連接的舊方法如下:
1.是否連接:
2. 網(wǎng)絡(luò)類型
但是在Android10之后,這些方法已過時(shí),官方不推薦使用,我們先來看下官方的源碼說明
左邊是Android10,右邊是Android9的源碼 , 在10上已經(jīng)標(biāo)記Deprecated,新加的注釋也推薦了使用的API。
還有一個(gè)舊廣播String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE" 在Android 9之后也廢棄,不推薦使用,之前的使用方法:
看下官方說明:
官方標(biāo)記Deprecated,是避免在高版本的設(shè)備上獲取返回的網(wǎng)絡(luò)狀態(tài)不對,并且給了推薦的API,以Android10為一個(gè)分界點(diǎn), 之后的版本都推薦使用新的API方法。
三. 官方推薦API
官方推薦:監(jiān)控 Android 中的互聯(lián)網(wǎng)連接,可以使用ConnectivityManager類,這是一個(gè)允許您查詢網(wǎng)絡(luò)狀態(tài)的系統(tǒng)服務(wù)類, 還有一個(gè)NetworkCapabilities類,代表活動(dòng)網(wǎng)絡(luò)的功能。
體使用方法如下:
- registerNetworkCallback():此函數(shù)注冊一個(gè)NetworkCallback對象來監(jiān)聽網(wǎng)絡(luò)狀態(tài)變化。它以一個(gè)NetworkCallback對象作為參數(shù)。
- unregisterNetworkCallback():此函數(shù)取消注冊以前注冊的NetworkCallback對象。
接下來重點(diǎn)關(guān)注NetworkCallback中的回調(diào)方法描述
回調(diào)方法 | 描述 |
onCapabilitiesChanged | 當(dāng)網(wǎng)絡(luò)狀態(tài)改變時(shí)回調(diào),比如信號(hào)強(qiáng)度切換,或者連接上網(wǎng)絡(luò)—>斷開網(wǎng)絡(luò),或者 mobile網(wǎng)絡(luò)切換到Wifi網(wǎng)絡(luò),都會(huì)回調(diào) |
onAvailable | 網(wǎng)絡(luò)連接成功 但不能判斷該網(wǎng)絡(luò)是否可以正常上網(wǎng) |
onUnavailable | 當(dāng)網(wǎng)絡(luò)連接超時(shí)或網(wǎng)絡(luò)請求達(dá)不到可用要求時(shí)調(diào)用 |
onBlockedStatusChanged | 當(dāng)訪問指定的網(wǎng)絡(luò)被阻止或解除阻塞時(shí)調(diào)用 |
onLosing | 當(dāng)網(wǎng)絡(luò)正在斷開連接時(shí)調(diào)用 |
onLost | 當(dāng)網(wǎng)絡(luò)已斷開連接時(shí)調(diào)用 |
onLinkPropertiesChanged | 當(dāng)網(wǎng)絡(luò)連接的屬性被修改時(shí)調(diào)用 |
接下來再說一下
NetworkCapabilities.java類中的NET_CAPABILITY_VALIDATED字段,描述為:
表示此網(wǎng)絡(luò)上的連接已成功驗(yàn)證。例如,對于具有NET_CAPABILITY_INTERNET的網(wǎng)絡(luò),這意味著已成功檢測到INTERNET連接。
通過實(shí)際log來描述說明一下:
1. 連接上可上網(wǎng)的wifi,可看到VALIDATED的標(biāo)記:
2. 連接上需要認(rèn)證和不能上網(wǎng)的wifi,找不到VALIDATED標(biāo)記:
3. 用數(shù)據(jù)流量上網(wǎng),可以看到VALIDATED的標(biāo)記:
我們可以通過networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)這個(gè)方法作為(連接可以正常上網(wǎng)的網(wǎng)絡(luò))判斷條件。進(jìn)一步通過networkCapabilities.hasTransport方法來判斷當(dāng)前的網(wǎng)絡(luò)類型。
四. 使用方法
看代碼更直接一點(diǎn):
MainActivity.java
@SuppressLint("NewApi") public class MainActivity extends AppCompatActivity { private static final String TAG = "ConnectManager"; private ConnectivityManager networkService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); networkService = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); if (networkService != null) { //注冊 NetworkCallBack networkService.registerDefaultNetworkCallback(networkCallBack); } } /* * 測試網(wǎng)絡(luò)工具類方法 * */ @Override protected void onResume() { super.onResume(); //Log.e(TAG, "=====在onResume方法中判斷 : isMobileNetwork :" + NetworkUtils.isMobileNetwork(this)); //Log.e(TAG, "=====在onResume方法中判斷 : isWifiNetwork :" + NetworkUtils.isWifiNetwork(this)); //Log.e(TAG, "=====在onResume方法中判斷 : getConnectedNetworkType :" + NetworkUtils.getConnectedNetworkType(this)); } @Override protected void onDestroy() { super.onDestroy(); if (networkService != null && networkCallBack != null) { networkService.unregisterNetworkCallback(networkCallBack); } } private final ConnectivityManager.NetworkCallback networkCallBack = new ConnectivityManager.NetworkCallback(){ //當(dāng)網(wǎng)絡(luò)狀態(tài)修改但仍舊是可用狀態(tài)時(shí)調(diào)用 @Override public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { super.onCapabilitiesChanged(network, networkCapabilities); if (NetworkUtils.isConnectedAvailableNetwork(getBaseContext())) { Log.d(TAG, "onCapabilitiesChanged ---> ====網(wǎng)絡(luò)可正常上網(wǎng)===網(wǎng)絡(luò)類型為: "+ NetworkUtils.getConnectedNetworkType(MainActivity.this)); } //表明此網(wǎng)絡(luò)連接驗(yàn)證成功 if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) { if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { Log.d(TAG, "===當(dāng)前在使用Mobile流量上網(wǎng)==="); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { Log.d(TAG, "====當(dāng)前在使用WiFi上網(wǎng)==="); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) { Log.d(TAG, "=====當(dāng)前使用藍(lán)牙上網(wǎng)====="); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { Log.d(TAG, "=====當(dāng)前使用以太網(wǎng)上網(wǎng)====="); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { Log.d(TAG, "===當(dāng)前使用VPN上網(wǎng)===="); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) { Log.d(TAG, "===表示此網(wǎng)絡(luò)使用Wi-Fi感知傳輸===="); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN)) { Log.d(TAG, "=====表示此網(wǎng)絡(luò)使用LoWPAN傳輸====="); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_USB)) { Log.d(TAG, "=====表示此網(wǎng)絡(luò)使用USB傳輸====="); } } } @Override public void onAvailable(@NonNull Network network) { super.onAvailable(network); Log.e(TAG, "==網(wǎng)絡(luò)連接成功,通知可以使用的時(shí)候調(diào)用====onAvailable==="); } @Override public void onUnavailable() { Log.e(TAG, "==當(dāng)網(wǎng)絡(luò)連接超時(shí)或網(wǎng)絡(luò)請求達(dá)不到可用要求時(shí)調(diào)用====onUnavailable==="); super.onUnavailable(); } @Override public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) { Log.e(TAG, "==當(dāng)訪問指定的網(wǎng)絡(luò)被阻止或解除阻塞時(shí)調(diào)用===onBlockedStatusChanged=="); super.onBlockedStatusChanged(network, blocked); } @Override public void onLosing(@NonNull Network network, int maxMsToLive) { Log.e(TAG, "==當(dāng)網(wǎng)絡(luò)正在斷開連接時(shí)調(diào)用===onLosing==="); super.onLosing(network, maxMsToLive); } @Override public void onLost(@NonNull Network network) { Log.e(TAG, "==當(dāng)網(wǎng)絡(luò)已斷開連接時(shí)調(diào)用===onLost==="); super.onLost(network); } @Override public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) { Log.e(TAG, "==當(dāng)網(wǎng)絡(luò)連接的屬性被修改時(shí)調(diào)用===onLinkPropertiesChanged==="); super.onLinkPropertiesChanged(network, linkProperties); } }; }
網(wǎng)絡(luò)工具類NetworkUtils.java
@SuppressLint("NewApi") public class NetworkUtils { private static final String TAG = "ConnectManager"; /** * Indicates this network uses a Cellular transport. */ public static final int TRANSPORT_CELLULAR = 0; /** * Indicates this network uses a Wi-Fi transport. */ public static final int TRANSPORT_WIFI = 1; /** * Indicates this network uses a Bluetooth transport. */ public static final int TRANSPORT_BLUETOOTH = 2; /** * Indicates this network uses an Ethernet transport. */ public static final int TRANSPORT_ETHERNET = 3; /** * Indicates this network uses a VPN transport. */ public static final int TRANSPORT_VPN = 4; /** * Indicates this network uses a Wi-Fi Aware transport. */ public static final int TRANSPORT_WIFI_AWARE = 5; /** * Indicates this network uses a LoWPAN transport. */ public static final int TRANSPORT_LOWPAN = 6; /** * Indicates this network uses a Test-only virtual interface as a transport. * @hide */ public static final int TRANSPORT_TEST = 7; /** * Indicates this network uses a USB transport. */ public static final int TRANSPORT_USB = 8; /** * >= Android 10(Q版本)推薦 * * 當(dāng)前使用MOBILE流量上網(wǎng) */ public static boolean isMobileNetwork(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); Network network = cm.getActiveNetwork(); if (null == network) { return false; } NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); if (null == capabilities) { return false; } return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); } /** * >= Android 10(Q版本)推薦 * * 當(dāng)前使用WIFI上網(wǎng) */ public static boolean isWifiNetwork(Context context) { ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); Network network = cm.getActiveNetwork(); if (null == network) { return false; } NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); if (null == capabilities) { return false; } return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); } /** * >= Android 10(Q版本)推薦 * * 當(dāng)前使用以太網(wǎng)上網(wǎng) */ public static boolean isEthernetNetwork(Context context) { ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); Network network = cm.getActiveNetwork(); if (null == network) { return false; } NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); if (null == capabilities) { return false; } return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); } /** * >= Android 10(Q版本)推薦 * * NetworkCapabilities.NET_CAPABILITY_INTERNET,表示此網(wǎng)絡(luò)應(yīng)該(maybe)能夠訪問internet * * 判斷當(dāng)前網(wǎng)絡(luò)可以正常上網(wǎng) * 表示此連接此網(wǎng)絡(luò)并且能成功上網(wǎng)。 例如,對于具有NET_CAPABILITY_INTERNET的網(wǎng)絡(luò),這意味著已成功檢測到INTERNET連接。 */ public static boolean isConnectedAvailableNetwork(Context context) { ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); Network network = cm.getActiveNetwork(); if (null == network) { return false; } NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); if (null == capabilities) { return false; } return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); } /** * >= Android 10(Q版本)推薦 * * 獲取成功上網(wǎng)的網(wǎng)絡(luò)類型 * value = { * TRANSPORT_CELLULAR, 0 表示此網(wǎng)絡(luò)使用蜂窩傳輸。 * TRANSPORT_WIFI, 1 表示此網(wǎng)絡(luò)使用Wi-Fi傳輸。 * TRANSPORT_BLUETOOTH, 2 表示此網(wǎng)絡(luò)使用藍(lán)牙傳輸。 * TRANSPORT_ETHERNET, 3 表示此網(wǎng)絡(luò)使用以太網(wǎng)傳輸。 * TRANSPORT_VPN, 4 表示此網(wǎng)絡(luò)使用VPN傳輸。 * TRANSPORT_WIFI_AWARE, 5 表示此網(wǎng)絡(luò)使用Wi-Fi感知傳輸。 * TRANSPORT_LOWPAN, 6 表示此網(wǎng)絡(luò)使用LoWPAN傳輸。 * TRANSPORT_TEST, 7 指示此網(wǎng)絡(luò)使用僅限測試的虛擬接口作為傳輸。 * TRANSPORT_USB, 8 表示此網(wǎng)絡(luò)使用USB傳輸 * } */ public static int getConnectedNetworkType(Context context) { ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); Network network = cm.getActiveNetwork(); if (null == network) { return -1; } NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); if (null == capabilities) { return -1; } if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) { if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { return NetworkCapabilities.TRANSPORT_CELLULAR; } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { return NetworkCapabilities.TRANSPORT_WIFI; } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) { return NetworkCapabilities.TRANSPORT_BLUETOOTH; } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { return NetworkCapabilities.TRANSPORT_ETHERNET; } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { return NetworkCapabilities.TRANSPORT_VPN; } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) { return NetworkCapabilities.TRANSPORT_WIFI_AWARE; } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN)) { return NetworkCapabilities.TRANSPORT_LOWPAN; } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_USB)) { return NetworkCapabilities.TRANSPORT_USB; } } return -1; } }
Android10之后,請使用新的API方法, 工具類可以根據(jù)業(yè)務(wù)需求去擴(kuò)展, 供參考。
總結(jié)
到此這篇關(guān)于Android獲取網(wǎng)絡(luò)連接狀態(tài)新方法的文章就介紹到這了,更多相關(guān)Android獲取網(wǎng)絡(luò)連接狀態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android中判斷網(wǎng)絡(luò)連接是否可用及監(jiān)控網(wǎng)絡(luò)狀態(tài)
- android 檢查網(wǎng)絡(luò)連接狀態(tài)實(shí)現(xiàn)步驟
- Android中監(jiān)聽判斷網(wǎng)絡(luò)連接狀態(tài)的方法
- Android中判斷網(wǎng)絡(luò)連接狀態(tài)的方法
- android檢測網(wǎng)絡(luò)連接狀態(tài)示例講解
- Android中檢查網(wǎng)絡(luò)連接狀態(tài)的變化無網(wǎng)絡(luò)時(shí)跳轉(zhuǎn)到設(shè)置界面
- Android使用BroadcastReceiver監(jiān)聽網(wǎng)絡(luò)連接狀態(tài)的改變
相關(guān)文章
React-Native Android 與 IOS App使用一份代碼實(shí)現(xiàn)方法
這篇文章主要介紹了React-Native Android 與 IOS App使用一份代碼實(shí)現(xiàn)方法的相關(guān)資料,這里舉例說明,該如何實(shí)現(xiàn)IOS和Android APP 都使用一樣的代碼,需要的朋友可以參考下2016-12-12Android實(shí)時(shí)獲取攝像頭畫面?zhèn)鬏斨罰C端思路詳解
這篇文章主要介紹了Android實(shí)時(shí)獲取攝像頭畫面?zhèn)鬏斨罰C端思路詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07Android?Studio實(shí)現(xiàn)帶三角函數(shù)對數(shù)運(yùn)算功能的高級計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Android?Studio實(shí)現(xiàn)帶三角函數(shù)對數(shù)運(yùn)算功能的高級計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05Flutter開發(fā)之對角棋游戲?qū)崿F(xiàn)實(shí)例詳解
這篇文章主要為大家介紹了Flutter開發(fā)之對角棋游戲?qū)崿F(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Android中自定義ImageView添加文字設(shè)置按下效果詳解
這篇文章主要給大家介紹了關(guān)于Android中自定義ImageView添加文字設(shè)置按下效果的相關(guān)資料,實(shí)現(xiàn)后的效果非常利用用戶的體驗(yàn),文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)下吧。2017-08-08