如何监测Android网络类型呢?

如何监测android网络类型:5g/4g/3g/2g能力
app可以通过了解所连接的网络类型来获益,例如启用某些功能需要5g提供的带宽和低延迟。如果只有2g或3g网络可用,加载时间会比较慢,因此我们可以对加载时间有一定的预期。
在这里,我们可以利用telephonymanager类来获取各种关于移动网络状态的信息,其中包括网络类型!不过,使用telephonymanager相当复杂,因为不同的android版本有不同的情况需要考虑。
下面我提供了一个示例应用程序,它可以检测我们所连接的移动网络类型,不仅仅是5g / 4g / 3g / 2g,还可以获取到具体的子类型。该应用使用了telephonymanager,并结合了jetpack compose、viewmodel和kotlin flow的编写方式。
使用telephonymanager注册以接收网络信息更新
获取telephonymanager的方法如下:
val telephonymanager =  context.getsystemservice(context.telephony_service) as telephonymanager  
...当上下文是一个context实例时。请注意,一些手机具有多个sim卡;如果您想查询特定的sim卡,请调用telephonymanager实例上的.createforsubscriptionid(simcardnumber)。
使用这个实例,我们现在可以获取网络信息更新。所使用的过程取决于android版本,即用户的android版本,而不是您应用的目标api级别。
android ≥ 12(api ≥ 31)
android 12及更高版本是最简单的情况,因为有一个专用的监听器,并且不需要权限。
要注册接收网络类型信息,我们使用registertelephonycallback(executor, telephonycallback)方法,如下所示:
// the thread executor used to run the listener. this governs how threads are created and// reused. here we use a single thread.val exec = executors.newsinglethreadexecutor()// create the callback objectval callback = object : telephonycallback(), telephonycallback.displayinfolistener {    override fun ondisplayinfochanged(telephonydisplayinfo: telephonydisplayinfo) {        //todo: this is next    }}// finally, register the callback so it can start receiving results.telephonymanager.registertelephonycallback(exec, callback)  
注销监听器,方法如下:
telephonymanager.unregistertelephonycallback(callback)
仅限 android 11 (api 30)
注册电话管理器回调的原始方法是使用 listen 方法。该方法接受各种类型的监听器;我们需要的是实现 ondisplayinfochanged 接口的监听器。
有趣的是,这个方法在一个 android 版本中就出现并消失了:
这需要 read_phone_state 权限。我们将在 ui 代码中稍后处理。现在我们将继续,假定我们已经拥有该权限。
// (at the top of the file)@file:suppress(deprecation) //suppressed as required to support old version// sdk 30 uses telephonymanager.listen() to listen for telephonydisplayinfo changes.// it requires read_phone_state permission.@suppress(override_deprecation)  //suppressed as required to support old version// this is the object that will receive the resultsval callback = object : phonestatelistener(exec) {    override fun ondisplayinfochanged(telephonydisplayinfo: telephonydisplayinfo) {        //todo: this is next    }}// start listening for resultstelephonymanager.listen(callback, phonestatelistener.listen_display_info_changed)  
注销监听使用下面代码:
telephonymanager.listen(callback, 0)  
android ≥ 7(api ≥ 24)
android 10及以下没有任何监听网络类型变化的方法。要支持较旧的版本,您需要实施一个循环,每隔几秒主动检查。
检查的代码如下:
val networktype = telephonymanager.datanetworktype  
这需要 read_phone_state 权限。
请注意,android 10及以下版本不能支持5g,因为5g仅在android 11及以上版本中可用。
返回的值:网络类型常量
在上述 android 11 和 ≥12 的代码中,会收到一个带有telephonydisplayinfo对象的回调。该对象包含一个 networktype 和一个 overridenetworktype。而在 android ≤10 的代码中,只会收到一个 networktype。
无论哪种情况,networktype 可以是以下之一:
val basetypestring = when(networktype) {    telephonymanager.network_type_cdma -> cdma    telephonymanager.network_type_1xrtt -> 1xrtt    telephonymanager.network_type_edge -> edge    telephonymanager.network_type_ehrpd -> ehrpd    telephonymanager.network_type_evdo_0 -> evdo rev 0    telephonymanager.network_type_evdo_a -> evdo rev a    telephonymanager.network_type_evdo_b -> evdo rev b    telephonymanager.network_type_gprs -> gprs    telephonymanager.network_type_gsm -> gsm    telephonymanager.network_type_hsdpa -> hsdpa    telephonymanager.network_type_hspa -> hspa    telephonymanager.network_type_hspap -> hspa+    telephonymanager.network_type_hsupa -> hsupa    telephonymanager.network_type_iden -> iden    telephonymanager.network_type_iwlan -> iwlan    telephonymanager.network_type_lte -> lte    telephonymanager.network_type_nr -> nr (new radio) 5g    telephonymanager.network_type_td_scdma -> td_scdma    telephonymanager.network_type_umts -> umts    else -> [unknown]}  
如果可用,overridenetworktype会为某些类型的4g和5g连接提供更多信息。以下是选项:
val overridestring = when(overridenetworktype) {    telephonydisplayinfo.override_network_type_nr_nsa -> 5g non-standalone    telephonydisplayinfo.override_network_type_nr_advanced -> 5g standalone (advanced)    telephonydisplayinfo.override_network_type_lte_advanced_pro -> lte advanced pro (5ge)    telephonydisplayinfo.override_network_type_lte_ca -> lte (carrier aggregation)    else -> null}  
可能的null处理:
val nettypestring = overridestring ?: basetypestring  
将其构建为一个kotlin + flows + viewmodel + compose应用程序
我在viewmodel中使用了一个kotlin callbackflow来设置上述监听器。如果您以前没有遇到过callbackflow,那就太棒了:它是一个流,可用于在外部api上创建一个监听器,当有人注册时,自动移除该监听器。
我使用.statein(viewmodelscope, sharingstarted.whilesubscribed(5000), null)将callbackflow从冷可观察对象转换为共享热可观察对象。这样,如果有多个消费者注册,就不会创建多个displayinfolisteners或phonestatelisteners。whilesubscribed(5000)部分确保可观察对象在所有消费者消失后仍保持存在一段时间,以防它们即将重新出现。(例如,在屏幕旋转的情况下会发生这种情况)。
在composable中,我使用collectasstatewithlifecycle()来确保监听器仅在应用程序位于前台时处于活动状态。


低功耗软件开发延长电池使用寿命
OPPO专利解读:手机屏幕可伸缩,采用屏下前置摄像头
空心杯电机参数_空心杯电机结构
数字可寻址照明接口技术的应用及优势介绍
联想正式发布了联想Z6 Pro这款手机主打超级视频AI四摄
如何监测Android网络类型呢?
霍尼韦尔称新款System Model H1量子计算机有新进展
用于超声波冷水水表和热量表基表标定装置的原理及设计
E5071B矢量网络分析仪300kHz-8.5GHz
安森美半导体与Plug and Play合力确保下一代的创新
华为宣布将在法国设立一个专门生产4G和5G设备的制造工厂
PCB中的黄金是什么
可预置数的4位计时器电路图
俄罗斯仪器将搭乘中国“郑和”号探测器前往小行星
将语音识别添加到电视遥控器
光伏企业晶科能源公布2020年第三季度财务业绩
iQOO Pro的性能为何能有这么强悍
大规模个性化定制研究综述!
智能制造有哪五个特点呢?
春节期间物联网技术助力着春运的防疫工作