App可以通过了解所连接的网络类型来获益,例如启用某些功能需要5G提供的带宽和低延迟。如果只有2G或3G网络可用,加载时间会比较慢,因此我们可以对加载时间有一定的预期。
在这里,我们可以利用TelephonyManager类来获取各种关于移动网络状态的信息,其中包括网络类型!不过,使用TelephonyManager相当复杂,因为不同的Android版本有不同的情况需要考虑。
下面我提供了一个示例应用程序,它可以检测我们所连接的移动网络类型,不仅仅是5G / 4G / 3G / 2G,还可以获取到具体的子类型。该应用使用了TelephonyManager,并结合了Jetpack Compose、ViewModel和Kotlin Flow的编写方式。
使用TelephonyManager注册以接收网络信息更新
获取TelephonyManager的方法如下:
valtelephonyManager= context.getSystemService(Context.TELEPHONY_SERVICE)asTelephonyManager
...当上下文是一个Context实例时。请注意,一些手机具有多个SIM卡;如果您想查询特定的SIM卡,请调用TelephonyManager实例上的.createForSubscriptionId(simCardNumber)。
使用这个实例,我们现在可以获取网络信息更新。所使用的过程取决于Android版本,即用户的Android版本,而不是您应用的目标API级别。
Android ≥ 12(API ≥ 31)
Android 12及更高版本是最简单的情况,因为有一个专用的监听器,并且不需要权限。
要注册接收网络类型信息,我们使用registerTelephonyCallback(Executor, TelephonyCallback)方法,如下所示:
//ThethreadExecutorusedtorunthelistener.Thisgovernshowthreadsarecreatedand //reused.Hereweuseasinglethread. valexec=Executors.newSingleThreadExecutor() //Createthecallbackobject valcallback=object:TelephonyCallback(),TelephonyCallback.DisplayInfoListener{ overridefunonDisplayInfoChanged(telephonyDisplayInfo:TelephonyDisplayInfo){ //TODO:Thisisnext } } //Finally,registerthecallbacksoitcanstartreceivingresults. telephonyManager.registerTelephonyCallback(exec,callback)
注销监听器,方法如下:
telephonyManager.unregisterTelephonyCallback(callback)
"""
仅限 Android 11 (API 30)
注册电话管理器回调的原始方法是使用 listen 方法。该方法接受各种类型的监听器;我们需要的是实现onDisplayInfoChanged接口的监听器。
有趣的是,这个方法在一个 Android 版本中就出现并消失了:
这需要READ_PHONE_STATE权限。我们将在 UI 代码中稍后处理。现在我们将继续,假定我们已经拥有该权限。
//(Atthetopofthefile) @file:Suppress("DEPRECATION")//Suppressedasrequiredtosupportoldversion //SDK30usesTelephonyManager.listen()tolistenforTelephonyDisplayInfochanges. //ItrequiresREAD_PHONE_STATEpermission. @Suppress("OVERRIDE_DEPRECATION")//Suppressedasrequiredtosupportoldversion //Thisistheobjectthatwillreceivetheresults valcallback=object:PhoneStateListener(exec){ overridefunonDisplayInfoChanged(telephonyDisplayInfo:TelephonyDisplayInfo){ //TODO:Thisisnext } } //Startlisteningforresults telephonyManager.listen(callback,PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
注销监听使用下面代码:
telephonyManager.listen(callback,0)
Android ≥ 7(API ≥ 24)
Android 10及以下没有任何监听网络类型变化的方法。要支持较旧的版本,您需要实施一个循环,每隔几秒主动检查。
检查的代码如下:
valnetworkType=telephonyManager.dataNetworkType
这需要READ_PHONE_STATE权限。
请注意,Android 10及以下版本不能支持5G,因为5G仅在Android 11及以上版本中可用。
返回的值:网络类型常量
在上述 Android 11 和 ≥12 的代码中,会收到一个带有TelephonyDisplayInfo对象的回调。该对象包含一个networkType和一个overrideNetworkType。而在 Android ≤10 的代码中,只会收到一个networkType。
无论哪种情况,networkType可以是以下之一:
valbaseTypeString=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->"EVDOrev0" TelephonyManager.NETWORK_TYPE_EVDO_A->"EVDOrevA" TelephonyManager.NETWORK_TYPE_EVDO_B->"EVDOrevB" 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(newradio)5G" TelephonyManager.NETWORK_TYPE_TD_SCDMA->"TD_SCDMA" TelephonyManager.NETWORK_TYPE_UMTS->"UMTS" else->"[Unknown]" }
如果可用,overrideNetworkType会为某些类型的4G和5G连接提供更多信息。以下是选项:
valoverrideString=when(overrideNetworkType){ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA->"5Gnon-standalone" TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED->"5Gstandalone(advanced)" TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO->"LTEAdvancedPro(5Ge)" TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA->"LTE(carrieraggregation)" else->null }
可能的null处理:
valnetTypeString=overrideString?:baseTypeString
将其构建为一个Kotlin + Flows + ViewModel + Compose应用程序
我在ViewModel中使用了一个KotlincallbackFlow来设置上述监听器。如果您以前没有遇到过callbackFlow,那就太棒了:它是一个流,可用于在外部API上创建一个监听器,当有人注册时,自动移除该监听器。
我使用.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), null)将callbackFlow从冷可观察对象转换为共享热可观察对象。这样,如果有多个消费者注册,就不会创建多个DisplayInfoListeners或PhoneStateListeners。WhileSubscribed(5000)部分确保可观察对象在所有消费者消失后仍保持存在一段时间,以防它们即将重新出现。(例如,在屏幕旋转的情况下会发生这种情况)。
在Composable中,我使用collectAsStateWithLifecycle()来确保监听器仅在应用程序位于前台时处于活动状态。
审核编辑:刘清
-
Android
+关注
关注
12文章
3851浏览量
125643 -
移动网络
+关注
关注
2文章
433浏览量
32448
原文标题:如何监测Android网络类型:5G/4G/3G/2G能力
文章出处:【微信号:哆啦安全,微信公众号:哆啦安全】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论