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()方法來(lái)判斷是否連接上, 判斷網(wǎng)絡(luò)連接的舊方法如下:
1.是否連接:

2. 網(wǎng)絡(luò)類型

但是在Android10之后,這些方法已過時(shí),官方不推薦使用,我們先來(lái)看下官方的源碼說明


左邊是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)不對(duì),并且給了推薦的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ù)注冊(cè)一個(gè)NetworkCallback對(duì)象來(lái)監(jiān)聽網(wǎng)絡(luò)狀態(tài)變化。它以一個(gè)NetworkCallback對(duì)象作為參數(shù)。
- unregisterNetworkCallback():此函數(shù)取消注冊(cè)以前注冊(cè)的NetworkCallback對(duì)象。
接下來(lái)重點(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ò)請(qǐng)求達(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)用 |
接下來(lái)再說一下
NetworkCapabilities.java類中的NET_CAPABILITY_VALIDATED字段,描述為:
表示此網(wǎng)絡(luò)上的連接已成功驗(yàn)證。例如,對(duì)于具有NET_CAPABILITY_INTERNET的網(wǎng)絡(luò),這意味著已成功檢測(cè)到INTERNET連接。
通過實(shí)際log來(lái)描述說明一下:
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方法來(lái)判斷當(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) {
//注冊(cè) NetworkCallBack
networkService.registerDefaultNetworkCallback(networkCallBack);
}
}
/*
* 測(cè)試網(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ò)請(qǐng)求達(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)。 例如,對(duì)于具有NET_CAPABILITY_INTERNET的網(wǎng)絡(luò),這意味著已成功檢測(cè)到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ò)使用僅限測(cè)試的虛擬接口作為傳輸。
* 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之后,請(qǐng)使用新的API方法, 工具類可以根據(jù)業(yè)務(wù)需求去擴(kuò)展, 供參考。
總結(jié)
到此這篇關(guān)于Android獲取網(wǎng)絡(luò)連接狀態(tài)新方法的文章就介紹到這了,更多相關(guān)Android獲取網(wǎng)絡(luò)連接狀態(tài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(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檢測(cè)網(wǎng)絡(luò)連接狀態(tài)示例講解
- Android中檢查網(wǎng)絡(luò)連接狀態(tài)的變化無(wú)網(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-12
設(shè)計(jì)簡(jiǎn)單的Android圖片加載框架
這篇文章主要為大家詳細(xì)介紹了Android圖片加載框架的簡(jiǎn)單設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
Android實(shí)時(shí)獲取攝像頭畫面?zhèn)鬏斨罰C端思路詳解
這篇文章主要介紹了Android實(shí)時(shí)獲取攝像頭畫面?zhèn)鬏斨罰C端思路詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
Android?Studio實(shí)現(xiàn)帶三角函數(shù)對(duì)數(shù)運(yùn)算功能的高級(jí)計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Android?Studio實(shí)現(xiàn)帶三角函數(shù)對(duì)數(shù)運(yùn)算功能的高級(jí)計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Flutter開發(fā)之對(duì)角棋游戲?qū)崿F(xiàn)實(shí)例詳解
這篇文章主要為大家介紹了Flutter開發(fā)之對(duì)角棋游戲?qū)崿F(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Android中自定義ImageView添加文字設(shè)置按下效果詳解
這篇文章主要給大家介紹了關(guān)于Android中自定義ImageView添加文字設(shè)置按下效果的相關(guān)資料,實(shí)現(xiàn)后的效果非常利用用戶的體驗(yàn),文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)下吧。2017-08-08

