曲径通幽 —— Android 息屏 TCP 连接管理

一、场景概述

设备与应用 :XIAOMI(HyperOS 12.X),安装 Flutter 应用通过 dart:io.Socket.connect(ip, port) 与局域网嵌入式设备建立 TCP 长连接后进行指令控制。

预期行为:在应用启动并连接设备后保持长连接,周期发送心跳;息屏/切后台后到切回前台唤醒无需重新建立连接,可稳定下发指令

实际问题:息屏一段时间后再亮屏即刻进行指令下发,下发指令失败,Flutter 日志出现大量:

log 复制代码
SocketException: Software caused connection abort (errno = 103)  
connect failed: ENETUNREACH (Network is unreachable)  

现象为网络中没有正常完成数据传输,被控设备未收到控制指令,控制无法生效


二、关键日志分析

  1. 系统网络层异常 通过 adb logcat | grep "Software caused connection abort" 抓取网络触发系统日志(IP 、MAC 地址已处理,日志主要关注异常语句)
log 复制代码
java.net.ConnectException: failed to connect to /3234:dv32:yyi:32::1 (port 156) from /:: (port 0) after 5000ms: 
connect failed: ENETUNREACH (Network is unreachable)

通过 Network is unreachable 可判定为网络权限类问题

  1. 系统网络策略
yaml 复制代码
I/JoyoseCloudControlManager3: network metered changed ... try to setNetworkAccessEnabled: false  
I/MiuiNetworkPolicy: updateUidState uid=10281, uidState=2  

try to setNetworkAccessEnabled 应用层有尝试打开网络的动作,但是失败了

grep 命令

shell 复制代码
db logcat | grep "JoyoseCloudControlManager3"
adb logcat | grep "MiuiNetworkPolicy"
  1. Wi-Fi 状态监测
makefile 复制代码
I/wificond: station_bandwidth: ?  
D/NetworkAccelerateSwitchService: getAverageWifiRssi:60  

grep 命令

shell 复制代码
adb logcat | grep "wificond"
adb logcat | grep "NetworkAccelerateSwitchService"

三、原因定位

维度 原因说明
TCP 空闲回收 Dart 默认无底层 TCP KeepAlive,心跳在后台/Doze 模式下被暂停,导致路由器或系统内核回收长连接(ARP、NAT 超时)。
Android 省电策略 Doze 模式 & Oreo 后台执行限制挂起应用网络;Wi-Fi 休眠(需要 WifiManager 锁或系统设置"睡眠时保持 Wi-Fi")。
HyperOS 神隐模式 小米"神隐模式"在息屏 4 min 后自动禁止后台联网,请参考 MIUI 文档:
  • "神隐模式"设置指南:c.mi.com/thread-...
  • 电源性能管理:dev.mi.com/.../power-man... |
    | 链路层中断 | 虚假联网状态下写入触发 ENETUNREACHECONNABORTED(errno=103),应用层无重连逻辑,报错后沉默。

四、Socket 保活与系统特性说明

  1. TCP KeepAlive

Dart 代码示例:

dart 复制代码
RawSocketOption ka = RawSocketOption(
  SocketOption.levelSocket, SocketOption.optKeepAlive, 1);
socket.setOption(ka);
  1. 前台 Service & 忽略电池优化

原生申请:

kotlin 复制代码
if (!powerManager.isIgnoringBatteryOptimizations(pkg)) {
  startActivity(Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
  Uri.parse("package:$pkg")))
  }
startForegroundService(...)
  1. 获得 Wi-Fi 锁
scss 复制代码
wifiManager.createWifiLock(WIFI_MODE_FULL_HIGH_PERF, "myLock").acquire()
  1. 神隐模式关闭

用户需在「设置→电源和性能→神隐模式」中排除 App;或引导用户手动操作。


五、解决策略

1. 息屏主动断开 + 亮屏重连

实现

scss 复制代码
```
@override
void didChangeAppLifecycleState(state) {
  if (state==AppLifecycleState.paused) {
    socket?.destroy(); heartbeat.cancel();
  } else if (state==AppLifecycleState.resumed) {
    _reconnectWithRetry();
  }
}
```

测试 Case

markdown 复制代码
1.  息屏 10 min → 亮屏 → 1s 内自动重连成功;
1.  网络中断后重连失败重试 3 次;
1.  快速切后台/前台循环 5 次无内存泄露。

2. 心跳优化 + TCP KeepAlive

实现:10 s → 5 s 心跳,启用 TCP KeepAlive,底层周期 60 s。

测试 Case

  1. Doze 模式下心跳仍偶尔成功;
  2. 路由重启后心跳发现失联并重连。

3. 前台服务 + 忽略电池优化

实现:在亮屏重连基础上,启动前台 Service,使 App 保持"可用"状态。

测试 Case

  1. 锁屏 30 min → 心跳不中断;
  2. Miui "神隐模式"开启时仍可通信(白名单已生效)。

4. WorkManager 周期唤醒

实现:使用 WorkManager 每隔 15 min 唤醒尝试重连。

测试 Case

  1. 在 Doze 深度保活窗口执行;
  2. 无需保活心跳,降低电量消耗。

六、方案对比与推荐

方案 优点 缺点 Flutter 兼容性
1. 息屏断开/亮屏重连 最简单、稳定绕过后台限制 息屏时无法控制;重连延迟 ⭐⭐⭐⭐⭐
2. 心跳+KeepAlive 保持长连接,自恢复能力强 Doze 下心跳不可靠;实现稍复杂 ⭐⭐⭐⭐
3. 前台 Service 最强保活,Doze 无感 用户体验成本;通知占用 ⭐⭐⭐
4. WorkManager 与系统兼容,省电 间隔不可低于15 min,不适合实时 ⭐⭐

推荐 :对于实时控制 场景,方案 1(息屏断开/亮屏重连)配合短心跳+重连最为合理。

  • 在 Flutter 层无需复杂原生改动;
  • 保证用户一亮屏即可恢复连接;
  • 与 Miui 系统兼容性最高。

七、总结

通过日志检索命令 快速定位 ENETUNREACH 与系统策略日志,结合 TCP 空闲回收、Android Doze 与 HyperOS "神隐模式"交互,确认息屏后台网络被系统挂起导致长连接假在线。

最优解是:

  1. 息屏时主动释放 TCP
  2. 亮屏时立即重连并恢复心跳
  3. 在必要时启用 TCP KeepAlive
    此策略实现成本低、可靠性高,且能在 Flutter 技术栈内完成,对绝大多数 Android 设备(尤其小米 HyperOS)均有效。
相关推荐
ZH15455891311 小时前
Flutter for OpenHarmony Python学习助手实战:面向对象编程实战的实现
python·学习·flutter
renke33642 小时前
Flutter for OpenHarmony:构建一个 Flutter 色彩调和师游戏,RGB 空间探索、感知色差计算与视觉认知训练的工程实现
flutter·游戏
游戏开发爱好者82 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
王码码20352 小时前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
黑码哥2 小时前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
Trouvaille ~2 小时前
【Linux】TCP Socket编程实战(一):API详解与单连接Echo Server
linux·运维·服务器·网络·c++·tcp/ip·socket
亓才孓2 小时前
[JDBC]元数据
android
独行soc2 小时前
2026年渗透测试面试题总结-17(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
金融RPA机器人丨实在智能3 小时前
Android Studio开发App项目进入AI深水区:实在智能Agent引领无代码交互革命
android·人工智能·ai·android studio
科技块儿3 小时前
利用IP查询在智慧城市交通信号系统中的应用探索
android·tcp/ip·智慧城市