一. 問題背景
????????Android12上,有的app模塊判斷當前網(wǎng)絡的類型和連接狀態(tài)時,還是使用的舊的API,導致返回的結果不準確,影響代碼邏輯判斷,本篇文章就這一問題,整理一下判斷網(wǎng)絡類型和連接狀態(tài)的新方法。
二. 原因分析
????????在Android 10以前的版本,大家都是通過NetworkInfo.java 的getType()方法獲取網(wǎng)絡類型,通過isConnected()方法來判斷是否連接上, 判斷網(wǎng)絡連接的舊方法如下:
1.是否連接:
?2.?網(wǎng)絡類型
?但是在Android10之后,這些方法已過時,官方不推薦使用,我們先來看下官方的源碼說明
?左邊是Android10,右邊是Android9的源碼 ,? ?在10上已經(jīng)標記Deprecated,新加的注釋也推薦了使用的API。
還有一個舊廣播String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"? 在Android 9之后也廢棄,不推薦使用,之前的使用方法:
看下官方說明:
?官方標記Deprecated,是避免在高版本的設備上獲取返回的網(wǎng)絡狀態(tài)不對,并且給了推薦的API,以Android10為一個分界點, 之后的版本都推薦使用新的API方法。
三.?官方推薦API
官方推薦:監(jiān)控 Android 中的互聯(lián)網(wǎng)連接,可以使用ConnectivityManager類,這是一個允許您查詢網(wǎng)絡狀態(tài)的系統(tǒng)服務類,? ?還有一個NetworkCapabilities類,代表活動網(wǎng)絡的功能。
體使用方法如下:
registerNetworkCallback():此函數(shù)注冊一個NetworkCallback對象來監(jiān)聽網(wǎng)絡狀態(tài)變化。它以一個NetworkCallback對象作為參數(shù)。
unregisterNetworkCallback():此函數(shù)取消注冊以前注冊的NetworkCallback對象。
接下來重點關注NetworkCallback中的回調方法描述
回調方法 |
描述 |
onCapabilitiesChanged |
當網(wǎng)絡狀態(tài)改變時回調,比如信號強度切換,或者連接上網(wǎng)絡—>斷開網(wǎng)絡,或者 mobile網(wǎng)絡切換到Wifi網(wǎng)絡,都會回調 |
onAvailable |
網(wǎng)絡連接成功 但不能判斷該網(wǎng)絡是否可以正常上網(wǎng) |
onUnavailable |
當網(wǎng)絡連接超時或網(wǎng)絡請求達不到可用要求時調用 |
onBlockedStatusChanged |
當訪問指定的網(wǎng)絡被阻止或解除阻塞時調用 |
onLosing |
當網(wǎng)絡正在斷開連接時調用 |
onLost |
當網(wǎng)絡已斷開連接時調用 |
onLinkPropertiesChanged |
當網(wǎng)絡連接的屬性被修改時調用 |
接下來再說一下
NetworkCapabilities.java類中的NET_CAPABILITY_VALIDATED字段,描述為:
表示此網(wǎng)絡上的連接已成功驗證。例如,對于具有NET_CAPABILITY_INTERNET的網(wǎng)絡,這意味著已成功檢測到INTERNET連接。
通過實際log來描述說明一下:
1. 連接上可上網(wǎng)的wifi,可看到VALIDATED的標記:
2.?連接上需要認證和不能上網(wǎng)的wifi,找不到VALIDATED標記:
?3.?用數(shù)據(jù)流量上網(wǎng),可以看到VALIDATED的標記:
我們可以通過networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)這個方法作為(連接可以正常上網(wǎng)的網(wǎng)絡)判斷條件。進一步通過networkCapabilities.hasTransport方法來判斷當前的網(wǎng)絡類型。
四. 使用方法
看代碼更直接一點:
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)絡工具類方法
* */
@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(){
//當網(wǎng)絡狀態(tài)修改但仍舊是可用狀態(tài)時調用
@Override
public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities);
if (NetworkUtils.isConnectedAvailableNetwork(getBaseContext())) {
Log.d(TAG, "onCapabilitiesChanged ---> ====網(wǎng)絡可正常上網(wǎng)===網(wǎng)絡類型為: "+ NetworkUtils.getConnectedNetworkType(MainActivity.this));
}
//表明此網(wǎng)絡連接驗證成功
if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
Log.d(TAG, "===當前在使用Mobile流量上網(wǎng)===");
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
Log.d(TAG, "====當前在使用WiFi上網(wǎng)===");
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) {
Log.d(TAG, "=====當前使用藍牙上網(wǎng)=====");
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
Log.d(TAG, "=====當前使用以太網(wǎng)上網(wǎng)=====");
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
Log.d(TAG, "===當前使用VPN上網(wǎng)====");
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) {
Log.d(TAG, "===表示此網(wǎng)絡使用Wi-Fi感知傳輸====");
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN)) {
Log.d(TAG, "=====表示此網(wǎng)絡使用LoWPAN傳輸=====");
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_USB)) {
Log.d(TAG, "=====表示此網(wǎng)絡使用USB傳輸=====");
}
}
}
@Override
public void onAvailable(@NonNull Network network) {
super.onAvailable(network);
Log.e(TAG, "==網(wǎng)絡連接成功,通知可以使用的時候調用====onAvailable===");
}
@Override
public void onUnavailable() {
Log.e(TAG, "==當網(wǎng)絡連接超時或網(wǎng)絡請求達不到可用要求時調用====onUnavailable===");
super.onUnavailable();
}
@Override
public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {
Log.e(TAG, "==當訪問指定的網(wǎng)絡被阻止或解除阻塞時調用===onBlockedStatusChanged==");
super.onBlockedStatusChanged(network, blocked);
}
@Override
public void onLosing(@NonNull Network network, int maxMsToLive) {
Log.e(TAG, "==當網(wǎng)絡正在斷開連接時調用===onLosing===");
super.onLosing(network, maxMsToLive);
}
@Override
public void onLost(@NonNull Network network) {
Log.e(TAG, "==當網(wǎng)絡已斷開連接時調用===onLost===");
super.onLost(network);
}
@Override
public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) {
Log.e(TAG, "==當網(wǎng)絡連接的屬性被修改時調用===onLinkPropertiesChanged===");
super.onLinkPropertiesChanged(network, linkProperties);
}
};
}
網(wǎng)絡工具類NetworkUtils.java文章來源:http://www.zghlxwxcb.cn/news/detail-712761.html
@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版本)推薦
*
* 當前使用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版本)推薦
*
* 當前使用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版本)推薦
*
* 當前使用以太網(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)絡應該(maybe)能夠訪問internet
*
* 判斷當前網(wǎng)絡可以正常上網(wǎng)
* 表示此連接此網(wǎng)絡并且能成功上網(wǎng)。 例如,對于具有NET_CAPABILITY_INTERNET的網(wǎng)絡,這意味著已成功檢測到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)絡類型
* value = {
* TRANSPORT_CELLULAR, 0 表示此網(wǎng)絡使用蜂窩傳輸。
* TRANSPORT_WIFI, 1 表示此網(wǎng)絡使用Wi-Fi傳輸。
* TRANSPORT_BLUETOOTH, 2 表示此網(wǎng)絡使用藍牙傳輸。
* TRANSPORT_ETHERNET, 3 表示此網(wǎng)絡使用以太網(wǎng)傳輸。
* TRANSPORT_VPN, 4 表示此網(wǎng)絡使用VPN傳輸。
* TRANSPORT_WIFI_AWARE, 5 表示此網(wǎng)絡使用Wi-Fi感知傳輸。
* TRANSPORT_LOWPAN, 6 表示此網(wǎng)絡使用LoWPAN傳輸。
* TRANSPORT_TEST, 7 指示此網(wǎng)絡使用僅限測試的虛擬接口作為傳輸。
* TRANSPORT_USB, 8 表示此網(wǎng)絡使用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è)務需求去擴展, 供參考。文章來源地址http://www.zghlxwxcb.cn/news/detail-712761.html
到了這里,關于Android 獲取網(wǎng)絡連接狀態(tài)新方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!