您的位置:首页 > 文旅 > 旅游 > 快速的网站建设_vi设计对企业的意义_seo工具软件_营销培训内容有哪些

快速的网站建设_vi设计对企业的意义_seo工具软件_营销培训内容有哪些

2024/12/27 8:46:02 来源:https://blog.csdn.net/android_cai_niao/article/details/144709599  浏览:    关键词:快速的网站建设_vi设计对企业的意义_seo工具软件_营销培训内容有哪些
快速的网站建设_vi设计对企业的意义_seo工具软件_营销培训内容有哪些

获取当前的网络类型,即想要知道当前的网络是wifi还是蜂窝网络还是网线:

fun getNetworkPreferences(context: Context): String {val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManagerval activeNetwork = connectivityManager.activeNetwork ?: return "No active network"val capabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return "Unknown capabilities"return when {capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> "Wi-Fi"capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> "Cellular"capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> "Ethernet"else -> "Other"}
}

早期,修改网络可以使用如下方法:

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.setNetworkPreference(ConnectivityManager.TYPE_WIFI);

该方法会尝试根据指定的网络类型来设置设备的默认网络连接。它影响全局网络行为,而不仅仅是当前应用。这个方法自 API 21 (Android 5.0) 开始已经被废弃,因此在现代 Android 开发中,它不再有实际的效果。Google 推荐使用更细粒度的网络请求管理方式(如 NetworkRequest 和 NetworkCallback)来实现类似的功能。从 Android 6.0(API 23)开始,应用无法直接更改全局网络设置,只能引导用户手动修改或通过请求网络临时切换。权限要求:

  • 获取网络状态需要 ACCESS_NETWORK_STATE 权限。
  • 临时切换网络需要 CHANGE_NETWORK_STATE 权限。

如果要修改网络,例如从移动数据切换到Wi-Fi,这需要用户交互,并且无法直接通过普通应用完成,以下是几种间接方法:

  1. 引导用户到网络设置界面

    fun openNetworkSettings(context: Context) {val intent = Intent(Settings.ACTION_WIRELESS_SETTINGS)context.startActivity(intent)
    }
    

    这会打开网络设置界面,这个界面上有WLAN、移动网络、飞行模式、Ethernet等的选项,方便我们对各种网络进行设置。对于打开网络设置的代码还有一个:

    fun openMobileNetworkSettings(context: Context) {val intent = Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS)context.startActivity(intent)
    }
    

    这个是跳到网络设置中的“移动网络设置”,即专门设置移动网络的,比如设置5G、4G、APN、移动数据开关等。

  2. 使用 NetworkRequestNetworkCallbackConnectivityManager 可以动态请求并使用符合特定条件的网络。

    fun requestCellularNetwork(context: Context) {val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManagerval request = NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build()connectivityManager.requestNetwork(request, object : ConnectivityManager.NetworkCallback() {override fun onAvailable(network: android.net.Network) {// 切换到此网络connectivityManager.bindProcessToNetwork(network)}})
    }
    

    注:这里做了两件事,首先是请求了蜂窝网络,然后请求到之后再将我们的应用绑定到这个网络,这样我们的应用就只会使用蜂窝网络,即使现在连接上wifi,其它的应用会使用wifi的流量,而我们的应用依然只使用蜂窝网络的流量,直到我们调用解除绑定:ConnectivityManager.unbindProcessFromNetwork()ConnectivityManager.setProcessDefaultNetwork(null)

如果不想请求任何网络,有什么用什么,但是我想持续监听网络的变化,比如什么时候网络断开了,什么时候网络恢复了,可使用registerNetworkCallback函数,示例如下:

val networkRequest = NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build()val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerNetworkCallback(networkRequest, object : ConnectivityManager.NetworkCallback() {override fun onAvailable(network: Network) {super.onAvailable(network)// 网络已可用}override fun onLost(network: Network) {super.onLost(network)// 网络丢失}
})

这里我们只监听wifi网络的变化,如果蜂窝网络发生变化我们就不知道,如果我只想知道当前默认网络的变化,默认网络即当前正在使用的网络,比如你当前有蜂窝网络,同时也连着WIFI,如果你的应用正在使用WIFI网络来进行网络传输,则WIFI网络为默认网络,不论当前默认是什么网络,想要监听它的变化可以使用registerDefaultNetworkCallback,示例如下:

val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {override fun onAvailable(network: Network) {super.onAvailable(network)// 当前默认网络可用}override fun onLost(network: Network) {super.onLost(network)// 当前默认网络丢失}
})
方法适用场景触发时机主要区别
requestNetwork()请求某个特定类型的网络连接(如 Wi-Fi、蜂窝)并等待连接。网络可用时触发 onAvailable(),不可用时触发 onUnavailable()用于请求网络连接,操作较为临时。
registerNetworkCallback()持续监听特定网络类型(Wi-Fi、蜂窝等)的状态变化。网络可用、丢失、切换时触发相应的回调。用于长期监听指定网络类型的状态变化。
registerDefaultNetworkCallback()只关心设备的当前默认网络(如 Wi-Fi 或蜂窝网络)。默认网络的变化(如切换 Wi-Fi、蜂窝数据等)触发。用于监听设备默认网络的状态变化,适用于对网络类型不关心的场景。

在通过 ConnectivityManager.registerNetworkCallback() 注册网络回调时,onUnavailable() 方法不会被调用。onUnavailable() 主要是在 requestNetwork() 请求网络时,系统无法满足网络请求时触发的回调。

注册网络回调时的回调触发情况:

  • onAvailable():当您注册的网络回调监听的网络类型(如 Wi-Fi、蜂窝网络等)变为可用时触发。
  • onLost():当设备断开与某个网络的连接时触发。比如设备当前使用的网络断开,或者网络切换发生时。

requestNetwork()、registerNetworkCallback()、registerDefaultNetworkCallback()会触发的所有回调汇总:

  1. requestNetwork()

    • onAvailable():请求的网络成功可用时触发。
    • onUnavailable():请求的网络无法满足时触发。(根据我的实验,不论是请求wifi还是移动网络,当请求的网络无法满足时,这个函数都不会被调用。我在两部手机上试的,不知道别的手机会不会有不同?
    • onLost():请求的网络丢失时触发。
  2. registerNetworkCallback()

    • onAvailable():当指定的网络类型变为可用时触发。
    • onLost():当指定的网络类型丢失时触发。
    • onCapabilitiesChanged():当网络的能力发生变化时触发(如带宽、延迟等)。
    • onLinkPropertiesChanged():当网络的链路属性变化时触发(如 IP 地址变化)。
  3. registerDefaultNetworkCallback()

    • onAvailable():当设备的默认网络变为可用时触发。
    • onLost():当设备的默认网络丢失时触发。
    • onCapabilitiesChanged():当默认网络的能力发生变化时触发(如网络速度、延迟变化等)。

为什么registerDefaultNetworkCallback()不会触发onLinkPropertiesChanged()

  1. onLinkPropertiesChanged(): 这个回调通常在 registerNetworkCallback() 方法中触发,用于监听 指定网络类型(如 Wi-Fi、蜂窝数据等)在连接时链路属性(LinkProperties)发生变化。链路属性包括 IP 地址、DNS 设置、网络接口等信息。它是为了监听更详细的网络层信息变化,而不仅仅是网络的可用性。

  2. registerDefaultNetworkCallback(): 这个方法的设计目的是监听 默认网络 的可用性和丢失状态,但并不关心默认网络的链路属性变化(如 IP 地址变化)。因此,onLinkPropertiesChanged() 不会在 registerDefaultNetworkCallback() 中触发。默认网络回调主要是关注网络的连接状态,而不是链路属性的细节变化。

  3. onLinkPropertiesChanged() 只有在您使用 registerNetworkCallback() 来监听特定网络类型时才会触发。也就是说,您需要关注某一特定的网络连接(例如 Wi-Fi 或蜂窝网络),并且当该网络的链路属性发生变化时,才会触发该回调。

设计目的:

  • registerDefaultNetworkCallback() 旨在提供设备 默认网络 的 连接/丢失状态变化,而 onLinkPropertiesChanged() 更多是用于检测 网络接口 的 链路属性变化。这些链路属性变化不一定与默认网络的连接状态变化直接相关,因此 onLinkPropertiesChanged() 不在默认网络回调中触发。

onCapabilitiesChanged()onLinkPropertiesChanged() 都是 ConnectivityManager.NetworkCallback 的回调方法,它们在不同的网络状态变化时触发,主要用于监听网络的能力和链路属性的变化。尽管它们都是在网络状态发生变化时触发的,但触发的具体条件有所不同。

  1. onCapabilitiesChanged()触发时机:

    • onCapabilitiesChanged() 会在网络 能力(capabilities) 发生变化时被调用。网络能力通常是与网络的 功能性特征 相关的信息,比如:
      • 网络是否支持互联网访问(NET_CAPABILITY_INTERNET)
      • 是否支持漫游(NET_CAPABILITY_MMS)
      • 网络的带宽、延迟、流量控制等能力
      • 是否支持对等连接(P2P)
      • 是否支持不加密的连接
      • 网络的优先级等。

    常见的触发场景:

    • 网络从不支持互联网访问切换为支持互联网。
    • 网络从高带宽模式切换到低带宽模式(例如,Wi-Fi 到 4G)。
    • 网络的能力发生其他变化,例如,支持某种类型的流量(如视频流、音频流)或变更网络类型。

    举例:当设备从 Wi-Fi 切换到蜂窝数据网络时,网络的能力会发生变化,因为蜂窝网络的能力(例如带宽、延迟、是否支持漫游等)和 Wi-Fi 网络有所不同。

  2. onLinkPropertiesChanged() 触发时机:

    • onLinkPropertiesChanged() 会在网络 链路属性(link properties) 发生变化时被调用。链路属性是与网络连接的 低层信息 相关的,比如:
      • IP 地址
      • DNS 配置
      • 网络接口类型(例如 Wi-Fi 接口或蜂窝接口)
      • 网络的路由设置

    常见的触发场景:

    • 网络的 IP 地址 发生变化(例如从 DHCP 获取新 IP)。
    • 网络的 DNS 设置 发生变化。
    • 网络的 路由配置 或 网络接口 发生变化。

    例子:当设备的 Wi-Fi 网络断开并重新连接时,它的链路属性(如 IP 地址、DNS 设置等)可能会发生变化,因此会触发 onLinkPropertiesChanged()。

onCapabilitiesChanged()onLinkPropertiesChanged() 的区别:

回调触发时机关注的变化举例
onCapabilitiesChanged()网络的能力(如支持互联网、带宽、延迟等)发生变化时触发网络能力(例如支持互联网、P2P、带宽等)1. 网络从不支持互联网切换为支持互联网。2. 网络从 4G 切换为 3G,带宽发生变化。
onLinkPropertiesChanged()网络的链路属性(如 IP 地址、DNS、路由等)发生变化时触发网络连接的低层属性(如 IP 地址、DNS)1. Wi-Fi 连接后,IP 地址或 DNS 设置变化。2. 使用 DHCP 获取新的 IP 地址。

对于connectivityManager.requestNetwork函数请求一个网络,我当前手机有移动网络,我想请求一个Wi-Fi网络,我设备当前的Wi-Fi开关是关闭状态,当我调用requestNetwork()函数后没有任何反应,而且onAvailableonUnavailableonLost函数都没有被调用。然后我打开WIFI开关,回调函数还是没有被调用,然后我连接Wifi,此时onAvailable被调用了,然后我断开wifi的连接,然后onLost被调用了。然后我又连上wifi,onAvailable又被调用了,再断开wifi(断开wifi或者关闭wifi开关),onLost又被调用了。

即使我已经打开了wifi开关,并且连接了一个wifi,然后只是断开了wifi,但是这个wifi的账号密码还是保存状态的,此时调用 requestNetwork()函数来请求wifi网络还是没有任何反应的,而且也没有回调被调用 。也是一样,当我手动连接上一个wifi后,onAvailable被调用,断开wifi的连接后onLost被调用,似乎onUnavailable从来不会被调用,不知道是不是因为手机设备版本的问题,还是API设计就是如此。

当我wifi是连接的,移动网络也是ok的,此时App本来默认就是会走wifi网络的,此时我调用requestNetwork()来请求移动网络,也是没有任何回调的,当我断开wifi时,移动网络变得可用了,此时之前的移动网络的请求中的onAvailable回调会被调用。

所以我感觉这个requestNetwork()真的就只是设置了一个监听器,跟registerNetworkCallback()没多大差别,没有什么请求不请求的操作。

对于connectivityManager.bindProcessToNetwork(network)绑定指定的网络,确实是可以的,比如我想绑定我的App就用移动网络,即使连了wifi也走移动的网络,不走wifi,经实验确实是OK的,wifi明明连接了,但是还是可以走移动的网络进行通信。反过来也一样,比如我想绑定WIFI网络,则当我断开WIFI后,即使现在移动网络是OK的,但是由于我绑定到了WIFI网络,则现在的网络请求就会失败,因为WIFI断开了,而且它不会走移动的网络。

requestNetwork()请求网络,网络有效时再绑定网络,这样好像也行不通,比如现在同时也是连着wifi的,此时你调用requestNetwork()请求移动网络时,onAvailable是不会被调用的,那就没办法在这个回调中调用绑定的代码了,直到你断开wifi时onAvailable才会被调用,如果wifi一直不断开就一直不会被调用。

所以,requestNetwork()的应用场景是怎样的?我真是想不明白。

如果要绑定特定网络,可以这样做:

fun bindToMobileNetwork(context: Context) {val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManagerval networks: Array<Network> = connectivityManager.allNetworksfor (network in networks) {val capabilities = connectivityManager.getNetworkCapabilities(network)if (capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {connectivityManager.bindProcessToNetwork(network)}}
}

如上代码是ChatGPT回答,但是经我实验也是行不通的,因为当wifi连接上之后,connectivityManager.allNetworks返回的数组中只有一个Network对象,且这个对象是Wifi的,所以也是没办法绑定到移动网络的。

connectivityManager.allNetworks明明返回的是一个数组,为什么我明明有移动网络,又连了WIFI,怎么返回的数组对象只有一个元素呢?这样的话,我猜测它应该是返回所有活跃的网络,活跃的网络即可以使用的网络,比如台式电脑可以接一台网线,然后再连上一个WIFI,此时电脑可以同时通往过网线或通过WIFI进行通信的,而且也不需要进行什么网络切换操作,这种情况我们就说网线网络和WIFI网络都是活跃的。再回到Android,由于系统做了限制,虽然我有移动网络和WIFI网络,但是系统只把WIFI设为活跃网络,此时我只能走WIFI的网络通信,移动网络是不通的,所以connectivityManager.allNetworks中只包含了wifi网络。既然它是能返回一个数组,说明是可以返回多个网络,那就得看系统的实现了,如果系统允许多个活跃网络同时存在,那么这个数组里面就会包含有多个网络,可能在这种情况下,我们调用requestNetwork()onAvailable就会被执行了。

根据ChartGPT回答,说requestNetwork() 本身不会强制切换网络,只会通知你请求的网络何时可用。且onUnavailable()是在请求网络时,且网络不可用时调用,但是根据我的实验,不管我请求wifi或是移动网络,但是请求的网络不可用时,onUnavailable()也不会被调用,只是当网络可用时onAvailable()会被调用,然后网络断开时onLost会被调用。

基于实验,我感觉requestNetwork()就是个鸡肋,反正我试过两部手机是没用的,这个设计的初衷应该是想让网络切换的,但是手机厂商基于使用的便利性都进行了修改,因为Wifi连接上了,确实就应该自动使用wifi的网络,而wifi断开后就自动使用移动网络,当连接wifi时,如果wifi信号很差,也可以自动切换到使用移动网络,这些工作都是由系统或搬家厂商实现的,但是有时候我就想直接绑定应该使用移动流量,但是requestNetwork()没办法请求到移动网络(如果当前wifi是连接着的话)。

但是绑定网络的那个函数是真的有用的:bindProcessToNetwork(network),一旦绑定了某个网络,你的app就只会使用这个网络进行通信了,除非你解除绑定,或者你的应用进程死了然后重新启动。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com