Flutter应用无网络连接时如何获取网络时间及监控系统时间修改?
无互联网环境下获取可信时间的方案
无互联网连接时无法实时获取最新的网络时间,所有无网可用的时间方案都基于有网时预先缓存的可信时间基准做推导
- 首次启动或有网时段定期同步NTP时间,缓存到本地持久化存储(比如
shared_preferences),同时记录当前的系统启动时长(该值不会随用户修改系统时间、时区发生变化) - 无网时可信时间计算逻辑:
缓存的NTP时间 + (当前系统启动时长 - 缓存NTP时记录的启动时长),只要设备未重启,该计算结果完全准确 - 设备重启兼容处理:重启后系统启动时长会重置,无网状态下可做降级处理:提示用户需要联网一次校准时间,或短时间内用缓存时间结合关机时长预估做临时计算,等有网后立刻重新校准
参考实现代码:
import 'package:ntp/ntp.dart'; import 'package:system_clock/system_clock.dart'; import 'package:shared_preferences/shared_preferences.dart'; // 有网时校准时间基准 Future<void> calibrateTime() async { final prefs = await SharedPreferences.getInstance(); // 获取NTP网络时间 DateTime ntpTime = await NTP.now(); // 获取当前系统启动时长(毫秒) int uptimeMs = SystemClock.uptime.inMilliseconds; // 持久化存储基准值 await prefs.setInt('cached_ntp_ms', ntpTime.millisecondsSinceEpoch); await prefs.setInt('cached_uptime_ms', uptimeMs); } // 任意场景下获取可信时间 Future<DateTime?> getTrustedTime() async { final prefs = await SharedPreferences.getInstance(); final cachedNtpMs = prefs.getInt('cached_ntp_ms'); final cachedUptimeMs = prefs.getInt('cached_uptime_ms'); // 无历史校准记录,提示需要联网 if (cachedNtpMs == null || cachedUptimeMs == null) return null; final currentUptimeMs = SystemClock.uptime.inMilliseconds; final trustedTimeMs = cachedNtpMs + (currentUptimeMs - cachedUptimeMs); return DateTime.fromMillisecondsSinceEpoch(trustedTimeMs); }
追踪系统时间被修改的方案
- 对比系统当前时间和上述方法推导的可信时间的差值:如果差值超过你设定的阈值(比如5分钟),即可判定用户修改了系统时间
- 监听系统时间变化广播:安卓端用
android_intent_plus监听ACTION_TIME_CHANGED、ACTION_DATE_CHANGED广播,iOS端监听NSSystemTimeZoneDidChangeNotification、UIApplicationSignificantTimeChangeNotification通知,收到广播后立刻触发时间校验逻辑 - 时区修改特殊处理:如果用户仅修改时区未修改时间,可统一使用UTC时间做业务计算,不需要触发异常判定
注意:上述方案可覆盖99%的普通用户场景,无法100%规避root/越狱设备的恶意篡改,金融、打卡等高安全要求场景,需要结合服务端时间校验做双重验证。
内容的提问来源于stack exchange,提问作者afsal.an
相关产品推荐
相关产品推荐

