Android监听网络变化
如果我们的Android终端(比如TV)支持wifi和有线网络同时接入,那么我们如何知道当前设备实际的网络出口是wifi还是有线网络呢
获取瞬时状态
一台 Android 设备可以同时保持多个连接。如需获取有关当前网络状态的信息,请先获取 ConnectivityManager 的实例
ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);
接下来,使用此实例获取对应用当前默认网络的引用:
Network currentNetwork = connectivityManager.getActiveNetwork();
通过对网络的引用,您的应用可以请求有关网络的信息:
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(currentNetwork);
LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);
NetworkCapabilities 和 LinkProperties
NetworkCapabilities 和 LinkProperties 对象可以提供系统了解的关于某个网络的所有属性。
LinkProperties 对象可以提供关于路由、链接地址、接口名称、代理信息(如有)和 DNS 服务器的信息。针对 LinkProperties 对象调用相关方法可以检索所需信息。
NetworkCapabilities 对象封装了有关网络传输及其功能的信息。
传输是网络运行的物理媒介的抽象形式。常见的传输示例包括以太网、Wi-Fi 和移动网络。VPN 和点对点 Wi-Fi 也可以传输。在 Android 上,一个网络可以同时拥有多个传输。例如,通过 Wi-Fi 和移动网络运行的 VPN。VPN 支持 Wi-Fi、移动网络和 VPN 传输。若要查找某个网络是否具有特定的传输,请使用 NetworkCapabilities.hasTransport(int) 方法和其中一个 NetworkCapabilities.TRANSPORT_* 常量。
功能描述了网络的属性。示例功能包括 MMS、NOT_METERED 和 INTERNET。具有 MMS 功能的网络可以收发彩信消息,不具有此功能的网络则不能。具有 NOT_METERED 功能的网络不会向用户收取流量费用。您的应用可以使用 NetworkCapabilities.hasCapability(int) 和其中一个 NetworkCapabilities.NET_CAPABILITY_* 常量来检查功能是否恰当。
最实用的 NET_CAPABILITY_* 常量包括:
-
NET_CAPABILITY_INTERNET:表示网络设置为访问互联网。这只是设置,而不是实际能够到达公共服务器。例如,网络可以设置为访问互联网,但受到强制门户的限制。运营商的移动网络通常具有
INTERNET功能,而本地点对点 Wi-Fi 网络通常没有。如需了解实际连接,请参阅NET_CAPABILITY_VALIDATED。 -
NET_CAPABILITY_NOT_METERED:表示网络不按流量计费。当用户由于资金、流量限制或电池性能问题而对严重流量消耗敏感时,可将网络归类为按流量计费的网络。 -
NET_CAPABILITY_NOT_VPN:表示网络不是虚拟专用网。 -
NET_CAPABILITY_VALIDATED:表示在系统探测网络时网络提供对公共互联网的实际访问。通过强制门户接入的网络或不提供域名解析的网络则不具备此功能。这是系统关于实际提供访问的网络所能知道的最接近真实情况的信息,尽管通过验证的网络原则上仍需要经过基于 IP 的过滤,或者由于信号差等问题而导致连接突然中断。 -
NET_CAPABILITY_CAPTIVE_PORTAL:表示在系统探测网络时网络具有强制门户。
还存在更多专用应用可能感兴趣的其他功能。如需了解详情,请参阅 NetworkCapabilities.hasCapability(int) 中的参数定义。
网络的功能可能随时发生变化。当系统检测到强制门户时,它会显示一条邀请用户登录的通知。在此过程中,网络具有 NET_CAPABILITY_INTERNET 和 NET_CAPABILITY_CAPTIVE_PORTAL 功能,但不具有 NET_CAPABILITY_VALIDATED 功能。
用户执行操作并登录到强制门户页面后,设备将能够访问公共互联网,并且网络将获得 NET_CAPABILITY_VALIDATED 功能而失去 NET_CAPABILITY_CAPTIVE_PORTAL 功能。
监听网络事件
同样,网络的传输可能动态变化。例如,VPN 可以自行重新配置,以使用刚刚出现的速度更快的网络,比如针对底层网络将移动网络切换为 Wi-Fi。在这种情况下,网络会失去 TRANSPORT_CELLULAR 传输而获得 TRANSPORT_WIFI 传输,同时保留 TRANSPORT_VPN 传输。
所有 Android 应用都有一个由系统确定的默认网络。系统通常首选不按流量计费的网络而非按流量计费的网络,首选网速较快的网络而非网速较慢的网络。
当应用发出网络请求(例如使用 HttpsURLConnection)时,系统会使用默认网络满足该请求。
在应用的整个生命周期内,设置为默认网络的网络可能随时发生变化。典型的例子是设备处于一个已知活跃、不按流量计费、速度快于移动网络的 Wi-Fi 接入点的覆盖范围内。设备会连接到此接入点,并将所有应用的默认网络切换到新的 Wi-Fi 网络。
当新网络成为默认网络时,应用打开的任何新连接都会使用此网络。一段时间后,上一个默认网络上的所有剩余连接都将被强制终止。如果知道默认网络发生变化的时间对应用很重要,它会按如下方式注册默认网络回调:
connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
Log.e(TAG, "The default network is now: " + network);
}
@Override
public void onLost(Network network) {
Log.e(TAG, "The application no longer has a default network. The last default network was " + network);
}
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
Log.e(TAG, "The default network changed capabilities: " + networkCapabilities);
}
@Override
public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
Log.e(TAG, "The default network changed link properties: " + linkProperties);
}
});
也就是说我们可以在onCapabilitiesChanged回调中获取当前的网络出口。
当然如果你不需要实时监听,只是单纯地想在某个时刻去获取网络出口类型,也可以通过下面的方式完成
Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
logger.d("Device is using wired connection");
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
logger.d("Device is using Wi-Fi connection");
} else {
logger.d("Device is using other type of connection");
}
参考
https://developer.android.google.cn/develop/connectivity/network-ops/reading-network-state?hl=zh-cn#java
浙公网安备 33010602011771号