Android 判断当前网络类型是否为5G 您所在的位置:网站首页 手机网络类型是nr Android 判断当前网络类型是否为5G

Android 判断当前网络类型是否为5G

2024-07-17 13:28| 来源: 网络整理| 查看: 265

2021.1.16更新     适配targetSdkVersion P(28)及更高的版本

项目中若存在判断当前网络类型,一般都会用到如下方法:

/** * get the network type * * @param ctx Context * @return networktype */ public static int getNetWorkType(Context ctx) { int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE); try { int defaultDataSubId = getSubId(); if (defaultDataSubId == -1) { networkType = tm.getNetworkType(); } else { try { Method dataNetworkType = TelephonyManager.class .getDeclaredMethod("getDataNetworkType", new Class[]{int.class}); dataNetworkType.setAccessible(true); networkType = (int) dataNetworkType.invoke(tm, defaultDataSubId); } catch (Throwable t) { t.printStackTrace(); } if (networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { networkType = tm.getNetworkType(); } } } catch (Throwable t) { t.printStackTrace(); } return networkType; } /** * get data sub id * * @return subId */ private static int getSubId() { int defaultDataSubId = -1; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); } return defaultDataSubId; }

至于networkType的取值,可参考TelephonyManager类。

使用上述方法,在5G网络之前都没问题,到5G网络时,查看Android Q源码,发现TelephonyManager类里增加了这么一个类型常量:

/** Current network is NR(New Radio) 5G. */ public static final int NETWORK_TYPE_NR = TelephonyProtoEnums.NETWORK_TYPE_NR; // 20.

意味着在5G网络下上述两个方法返回的networkType应该是20,实际测试了下,然并卵,返回的是13(NETWORK_TYPE_LTE,表示4G)。 是Android系统出问题了?还是厂商定制ROM出问题了? 查看运营商5G网络的搭建,发现现在5G网络基本都是通过4G增强型基站发射,也就是所谓的非独立组网(NSA),所以系统获取到的是NETWORK_TYPE_LTE,是没错的。只有独立5G组网(SA),系统才会返回NETWORK_TYPE_NR。 可厂商的手机明明就可以显示5G网络标识,不一致了,怎么搞?

网传华为提供了自己的接口判断是否为5G网络,亲试确实可正常使用,如下代码:

/** * get huawei network type * * @return networkType */ public static int getHwNetworkType(Context ctx) { int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; if (VERSION.SDK_INT >= VERSION_CODES.O && ctx.checkSelfPermission(permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { try { TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE); ServiceState ss; int subId = SubscriptionManager.getDefaultDataSubscriptionId(); if (subId < 0) { ss = tm.getServiceState(); } else { Class classTm = TelephonyManager.class; Method method = classTm .getDeclaredMethod("getServiceStateForSubscriber", new Class[]{int.class}); method.setAccessible(true); Object objSs = method.invoke(tm, subId); ss = (ServiceState) objSs; } Method hwGetNetworkMethod = ServiceState.class.getMethod("getHwNetworkType"); hwGetNetworkMethod.setAccessible(true); Integer hwNetType = (Integer) hwGetNetworkMethod.invoke(ss); if (hwNetType != null) { networkType = hwNetType; } } catch (Exception e) { QLog.e(tag, QLog.USR, "getHwNetworkType throw ex", e); } } return networkType; }

华为的搞定了,其它厂商呢?找了半天没找到类似接口,有点小无奈...

仔细看华为提供的接口,里面用到了ServiceState,在Android Q上此类有getNrState方法,"nr"跟NETWORK_TYPE_NR貌似有点儿像,也许这个方法正确判断5G,但是由于系统限制,此方法无法反射调用。但里面的nrState在toString()方法里面出现了,是不是可以搞事情?于是有了下面通用的方法:

/** * network util */ public class NetworkUtil { public static final int NETWORK_TYPE_NR = 20; public static final int SDK_VERSION_Q = 29; /** * get the network type * * @param ctx Context * @return networkType */ public static int getNetWorkType(Context ctx) { int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE); try { int defaultDataSubId = getSubId(); if (defaultDataSubId == -1) { networkType = tm.getNetworkType(); } else { Object obj = ReflectionUtil.invokeMethod(tm, "android.telephony.TelephonyManager", "getDataNetworkType", new Class[]{int.class}, defaultDataSubId); if (obj instanceof Integer) { networkType = (Integer) obj; } if (networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { networkType = tm.getNetworkType(); } } } catch (Throwable t) { t.printStackTrace(); } if (networkType == TelephonyManager.NETWORK_TYPE_LTE) { networkType = adjustNetworkType(ctx, networkType); } return networkType; } /** * get the 5G network type * * @param ctx Context * @param networkTypeFromSys this method can be call only when networkTypeFromSys = 13(LET) * @return correct network type */ private static int adjustNetworkType(Context ctx, int networkTypeFromSys) { int networkType = networkTypeFromSys; if (VERSION.SDK_INT >= SDK_VERSION_Q && ctx.checkSelfPermission(permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { try { TelephonyManager tm = (TelephonyManager) ctx .getSystemService(Context.TELEPHONY_SERVICE); ServiceState ss = null; int defaultDataSubId = getSubId(); if (defaultDataSubId == -1) { ss = tm.getServiceState(); } else { Object obj = ReflectionUtil .invokeMethod(tm, "android.telephony.TelephonyManager", "getServiceStateForSubscriber", new Class[]{int.class}, defaultDataSubId); if (obj instanceof ServiceState) { ss = (ServiceState) obj; } if (ss == null) { ss = tm.getServiceState(); } } if (ss != null && isServiceStateFiveGAvailable(ss.toString())) { networkType = NETWORK_TYPE_NR; } } catch (Throwable t) { t.printStackTrace(); } } return networkType; } /** * get data sub id * * @return subId */ private static int getSubId() { int defaultDataSubId = -1; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); } return defaultDataSubId; } /** * check the service state str is 5G * * @param ss services state str * @return true if is 5G */ private static boolean isServiceStateFiveGAvailable(String ss) { boolean available = false; if (!TextUtils.isEmpty(ss) && (ss.contains("nrState=NOT_RESTRICTED") || ss.contains("nrState=CONNECTED"))) { available = true; } return available; } }

此方法为通用方法,使用时只需调用NetworkUtil#getNetWorkType(Context)即可,当然前提还得先获取下READ_PHONE_STATE权限,各大厂商皆可用。

上述代码已适配targetSdkVersion P(28)及更高的版本,ReflectionUtil代码可参考这篇文章

转载请注明出处:https://www.jianshu.com/p/f63cd36f7a2b



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有