一. 前言

1. NetworkInfo的过时

Android 编译sdk版本为29时,NetworkInfo 过时了。

我们以前都是通过NetworkInfo的isConnected来判断网络是否连接,NetworkInfo的getType来判断网络连接类型。

2. NetworkCapabilities的使用

我们将使用NetworkCapabilities来代替NetworkInfo判断网络是否连接,以及网络的连接类型。

3. 记住在清单文件中添加网络状态查询权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="swu.xl.networkstate">

<!--查看网络状态权限-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

二. 判断当前网络是否连接

1. 是否联网的判断方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 判断是否联网
*/
private boolean isOnline(@NonNull Context context){
//获取 ConnectivityManager
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert connectivityManager != null;

//如果版本大于 Build.VERSION_CODES.M (23)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

//获取 NetWork
Network network = connectivityManager.getActiveNetwork();

if(network != null) {
//获取 NetworkCapabilities
NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);

return (networkCapabilities != null && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
}

}else {

//获取NetworkInfo
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

return (networkInfo != null && networkInfo.isConnected());
}

return false;
}

2. hasCapability

1
2
3
4
5
6
7
/**
* Tests for the presence of a capability on this instance.
*
* @param capability the capabilities to be tested for.
* @return {@code true} if set on this instance.
*/
public boolean hasCapability(@NetCapability int capability)

capability 可以是 NetworkCapabilities.NET_CAPABILITY_INTERNET ,更多的参数可以查看系统源码。

1
2
3
4
5
/**
* Indicates that this network should be able to reach the internet.
* 意思就是可以联网
*/
public static final int NET_CAPABILITY_INTERNET = 12;

3. 为什么使用 Build.VERSION_CODES.M 区分版本

getActiveNetwork 这个方法最低使用 API 是 Build.VERSION_CODES.M(23)。

三. 判断当前网络的状态

1. 网络状态的判断方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* 判断当前网络状态
* @param context
* @return
*/
private boolean testNetWorkState(@NonNull Context context){
//获取 ConnectivityManager
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert connectivityManager != null;

//如果版本大于23
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

//获取 NetWork
Network network = connectivityManager.getActiveNetwork();

if(network!=null){
//获取 NetworkCapabilities
NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);

if(networkCapabilities != null){
if(networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)){
//WIFI
Toast.makeText(context, "WIFI", Toast.LENGTH_SHORT).show();
return true;
}else if(networkCapabilities.hasTransport(TRANSPORT_CELLULAR)){
//移动数据
Toast.makeText(context, "mobile", Toast.LENGTH_SHORT).show();
return true;
}
}
}

}else {
//获取NetworkInfo
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

if (networkInfo != null) {
if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
//WIFI
Toast.makeText(context, "WIFI", Toast.LENGTH_SHORT).show();
return true;
} else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
//移动数据
Toast.makeText(context, "mobile", Toast.LENGTH_SHORT).show();
return true;
}
}
}

return false;
}

2. hasTransport

1
2
3
4
5
6
7
8
9
/**
* Tests for the presence of a transport on this instance.
*
* @param transportType the transport type to be tested for.
* @return {@code true} if set on this instance.
*/
public boolean hasTransport(@Transport int transportType) {
return isValidTransport(transportType) && ((mTransportTypes & (1 << transportType)) != 0);
}

transportType 参数的类型如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* 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
*/
@TestApi
public static final int TRANSPORT_TEST = 7;

四. 监听网络状态的变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public class MainActivity extends AppCompatActivity {

//回调
ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){

//可用网络接入
//当我们的网络的某个能力发生了变化回调,会回调多次
@Override
public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
//一般在此处获取网络类型然后判断网络类型

//Toast.makeText(MainActivity.this, "网络接入", Toast.LENGTH_SHORT).show();
}

//网络可用的回调
@Override
public void onAvailable(@NonNull Network network) {
//和 onLost 成对出现

Toast.makeText(MainActivity.this, "网络可用", Toast.LENGTH_SHORT).show();
}

//网络断开
@Override
public void onLost(@NonNull Network network) {
//如果通过ConnectivityManager#getActiveNetwork()返回null,表示当前已经没有其他可用网络了。

Toast.makeText(MainActivity.this, "网络断开", Toast.LENGTH_SHORT).show();
}
};

//注册回调
private void registerNetworkCallback(Context context) {
//获取 ConnectivityManager
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert connectivityManager != null;

//获取 NetworkRequest 的 Builder
NetworkRequest.Builder builder = new NetworkRequest.Builder();
//强制使用蜂窝数据网络-移动数据
//builder.addTransportType(TRANSPORT_CELLULAR);
//强制使用wifi网络
//builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);

//注册
NetworkRequest networkRequest = builder.build();
connectivityManager.registerNetworkCallback(networkRequest,callback);
}

//注销回调
private void unregisterNetworkCallback(Context context) {
//获取 ConnectivityManager
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert connectivityManager != null;

//注销
connectivityManager.unregisterNetworkCallback(callback);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

@Override
protected void onStart() {
super.onStart();

registerNetworkCallback(this);
}

@Override
protected void onStop() {
super.onStop();

unregisterNetworkCallback(this);
}
}

五. 源码参考

NetworkState

参考文章

Android多网络环境(wifi,mobile)下强制在某个网络(mobile)访问服务端以及适配

android权限(permission)大全

Android网络状态获取类 在api 29中 NetworkInfo Deprecated

android10解决NetworkInfo废弃替代NetworkInfo isConnected()问题

android 5.0 以上监听网络变化