安卓工控4G网络实时监听:网络状态、信号强度、联网类型精准监听方案
安卓工控4G网络实时监听网络状态、信号强度、联网类型精准监听方案大家好我是黒漂技术佬。从今天开始咱们进入第二篇章4G网络稳定性专题。做无人售货柜的兄弟们谁没被网络坑过系统状态栏显示4G满格结果MQTT断了、数据发不出去、后台显示离线——这就是传说中的假联网。今天咱们就把网络监听这件事彻底搞明白从系统状态到真实连通性从信号强度到基站切换一网打尽。一、为什么系统的网络状态不可信先给新手朋友科普一下为什么不能直接用系统API判断网络。系统API告诉你的 vs 真实情况系统API返回实际可能情况NETWORK_STATE_CONNECTED连上了4G基站但基站出口断了信号满格信号强但带宽为0基站拥塞类型是LTE实际降速到2G了只是显示4G网络可用DNS挂了啥都解析不了核心问题系统只判断有没有连上网卡/基站不判断能不能真正访问互联网。这就好比你家路由器开着但宽带欠费了——WiFi满格就是上不了网。二、网络状态监听三层模型我总结了一套三层网络监听模型从外到内逐层确认第一层接口层 —— 4G模块在不在有没有数据连接 ↓ 第二层网络层 —— 能不能Ping通DNS能不能解析 ↓ 第三层业务层 —— MQTT连不连得上业务接口通不通第一层接口状态监听系统广播监听系统的网络变化广播知道网卡的连接状态publicclassNetworkStateReceiverextendsBroadcastReceiver{OverridepublicvoidonReceive(Contextcontext,Intentintent){ConnectivityManagercm(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfoinfocm.getActiveNetworkInfo();if(info!nullinfo.isConnected()){// 网络接口连接了但不一定能上网inttypeinfo.getType();// TYPE_MOBILE / TYPE_WIFIStringsubtypeinfo.getSubtypeName();// LTE / HSDPA / EDGE...notifyInterfaceConnected(type,subtype);}else{// 网络接口断开了notifyInterfaceDisconnected();}}}Android 7.0 推荐用 NetworkCallbackConnectivityManagercmgetSystemService(ConnectivityManager.class);cm.registerDefaultNetworkCallback(newConnectivityManager.NetworkCallback(){OverridepublicvoidonAvailable(Networknetwork){// 网络可用}OverridepublicvoidonLost(Networknetwork){// 网络丢失}OverridepublicvoidonCapabilitiesChanged(Networknetwork,NetworkCapabilitiescaps){// 网络能力变化比如从4G掉到2GbooleanisInternetcaps.hasCapability(NET_CAPABILITY_INTERNET);booleanis4Gcaps.hasTransport(TRANSPORT_CELLULAR);}});第二层真实连通性检测探针检测接口连上了不代表能上网得自己探一下publicclassNetworkProbe{// 用多个探测点避免单点故障privatestaticfinalString[]PROBE_URLS{http://www.baidu.com,http://connect.rom.miui.com/generate_204,http://your-server.com/health};/** * 检测真实网络连通性 * 注意必须在子线程执行 */publicstaticbooleanprobeRealConnectivity(){for(Stringurl:PROBE_URLS){try{HttpURLConnectionconn(HttpURLConnection)newURL(url).openConnection();conn.setRequestMethod(GET);conn.setConnectTimeout(3000);conn.setReadTimeout(3000);conn.connect();intcodeconn.getResponseCode();if(code200||code204){returntrue;}}catch(Exceptione){// 这个探测点失败试下一个}}returnfalse;}}探测策略网络变化时立刻探一次正常情况下每5分钟探一次疑似弱网时提高探测频率多个探测点轮询避免探测服务器挂了误判第三层业务连通性检测网络通了不代表你的业务能用比如MQTT服务器挂了publicclassBusinessConnectivityChecker{/** * 综合判断业务是否可用 */publicintgetBusinessNetworkLevel(){if(!NetworkManager.isInterfaceConnected()){returnNET_LEVEL_DISCONNECTED;// 0 - 完全断开}if(!NetworkProbe.probeRealConnectivity()){returnNET_LEVEL_FAKE_CONNECTED;// 1 - 假联网}if(!MqttManager.getInstance().isConnected()){returnNET_LEVEL_NET_OK_BIZ_FAIL;// 2 - 网通但业务不通}returnNET_LEVEL_FULL_WORKING;// 3 - 完全正常}}三、4G信号强度实时采集光知道通不通还不够信号强弱直接影响稳定性。获取信号强度publicclassSignalStrengthMonitor{privateTelephonyManagertelephonyManager;privatePhoneStateListenerphoneStateListener;publicvoidstartMonitor(){telephonyManager(TelephonyManager)App.getContext().getSystemService(Context.TELEPHONY_SERVICE);phoneStateListenernewPhoneStateListener(){OverridepublicvoidonSignalStrengthsChanged(SignalStrengthsignalStrength){super.onSignalStrengthsChanged(signalStrength);// 获取LTE信号强度intlevelsignalStrength.getLevel();// 0-4 级intdbmgetLteDbm(signalStrength);// 真实dBm值onSignalChanged(level,dbm);}};telephonyManager.listen(phoneStateListener,PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);}/** * 从SignalStrength中解析LTE的dBm * 不同厂商ROM实现不一样需要适配 */privateintgetLteDbm(SignalStrengthsignalStrength){try{// 反射获取LTE信号MethodmethodsignalStrength.getClass().getMethod(getLteDbm);return(int)method.invoke(signalStrength);}catch(Exceptione){// 降级处理return-120signalStrength.getLevel()*20;}}}信号强度等级参考dBm范围等级说明-50 ~ -70极好满格非常稳定-70 ~ -85良好正常使用没问题-85 ~ -100一般弱网边缘可能丢包-100 ~ -110较差经常断连需要优化 -110极差几乎不可用经验值售货柜设备信号低于-100dBm就要考虑装信号放大器或者换位置了。四、基站切换与网络抖动识别4G网络还有个坑——基站切换。设备移动或者基站负载变化时会从一个基站切到另一个中间有短暂断网。基站切换监听publicclassCellSwitchMonitor{privateintlastCellId-1;publicvoidcheckCellSwitch(){TelephonyManagertm(TelephonyManager)App.getContext().getSystemService(Context.TELEPHONY_SERVICE);try{CellInfocellInfotm.getAllCellInfo().get(0);intcurrentCellIdgetCellId(cellInfo);if(lastCellId!-1lastCellId!currentCellId){// 基站切换了onCellSwitched(lastCellId,currentCellId);}lastCellIdcurrentCellId;}catch(Exceptione){// 部分设备拿不到基站信息}}}网络抖动防抖基站切换会导致短暂断网这时候不要立刻触发重连逻辑加个防抖publicclassNetworkDebouncer{privatestaticfinallongDEBOUNCE_DELAY3000;// 3秒防抖privateHandlerhandlernewHandler();privateRunnabledisconnectRunnable;/** * 网络断开时调用 */publicvoidonNetworkDisconnected(){// 延迟3秒再确认是真断了防止基站切换误判if(disconnectRunnable!null){handler.removeCallbacks(disconnectRunnable);}disconnectRunnable()-{// 3秒后还没恢复才认为是真的断了notifyRealDisconnected();};handler.postDelayed(disconnectRunnable,DEBOUNCE_DELAY);}/** * 网络恢复时调用 */publicvoidonNetworkConnected(){if(disconnectRunnable!null){handler.removeCallbacks(disconnectRunnable);disconnectRunnablenull;}notifyConnected();}}五、网络状态日志与上报网络问题排查全靠日志一定要记详细本地网络日志publicclassNetworkLogger{// 记录网络状态变化publicvoidlogNetworkChange(intoldState,intnewState,Stringreason){StringlogString.format([%s] NET_CHANGE: %d - %d, reason%s, signal%ddbm,TimeUtils.formatNow(),oldState,newState,reason,SignalMonitor.getCurrentDbm());// 写入本地日志文件FileLogger.write(network.log,log);}// 定期记录网络质量publicvoidlogNetworkQuality(){StringlogString.format([%s] NET_QUALITY: level%d, dbm%d, type%s, ping%dms,TimeUtils.formatNow(),NetworkManager.getNetworkLevel(),SignalMonitor.getCurrentDbm(),NetworkManager.getNetworkType(),NetworkProbe.getLastPingTime());FileLogger.write(network_quality.log,log);}}关键指标上报后台把核心网络指标定期上报方便后台统计分析在线时长 / 离线次数平均信号强度基站切换次数网络抖动频率流量使用情况六、踩坑经验坑1不同厂商ROM信号强度API不一致现象同一套代码A品牌能拿到dBmB品牌返回0原因各家改了SignalStrength的内部实现解决多试几种反射方式拿不到就降级用getLevel()坑2WiFi和4G同时存在时的优先级现象设备插了网线又有4G系统优先用WiFi但WiFi断了不会自动切4G解决自己做网络切换策略检测主网络不通时主动请求切换数据网络坑3Android 12 权限收紧现象拿不到基站信息、信号强度不准原因高版本需要ACCESS_FINE_LOCATION权限解决申请定位权限工控设备一般都能拿到七、总结4G网络监听的核心不要相信系统API要自己探、多层确认。第一层看接口4G模块连没连上第二层看连通能不能真的上网探针检测第三层看业务MQTT、接口通不通再加上信号强度、基站切换、防抖处理把这套做好假联网的问题就能精准识别不会再出现系统显示在线但设备失联的尴尬情况。我是黒漂技术佬专注无人零售物联网实战。下一篇咱们聊《弱网断网自动重试机制》网络断了怎么优雅地重连既不浪费流量又能快速恢复。有售货柜网络相关的坑欢迎私信交流大家一起避坑~