这是 Android 时间 API 中最核心、也是最容易混淆的一对概念。尤其在车机/系统级开发中,选错一个就可能导致逻辑失效甚至严重 Bug。
一句话结论(先看这个)
场景 用哪一个
计时、超时、心跳、动画、日志间隔 ✅ SystemClock.elapsedRealtime()
展示给用户看的时间(年月日时分秒) ✅ System.currentTimeMillis()
车机开机 → 时间同步前 ❌ 不要用 currentTimeMillis()
需要绝对不回退的时间 ✅ elapsedRealtime()
二、核心区别对比表(非常重要)
维度 System.currentTimeMillis SystemClock.elapsedRealtime
时间基准 1970-01-01 00:00:00 UTC 设备开机那一刻
是否受用户修改 ✅ 会 ❌ 不会
是否受 NTP 同步影响 ✅ 会(可能跳变) ❌ 不会
是否会回退 ✅ 可能(时间校正) ❌ 永不回退
是否适合计时 ❌ 不适合 ✅ 非常适合
车机开机初期是否可信 ❌ 不可信 ✅ 完全可信
是否包含休眠时间 ✅ 包含 ✅ 包含
典型用途 日历、证书、UI 时间 超时、性能、心跳
三、为什么车机一定要分清?
1️⃣ currentTimeMillis() 在车机上不可信
// 车机刚开机
long t1 = System.currentTimeMillis();
// 可能是 1970、2020、甚至 2000 年
// 两分钟后 NTP 同步
long t2 = System.currentTimeMillis();
// 突然变成 2026 年
✅ 时间会跳变
❌ 可能倒退
❌ 不适合做逻辑判断
2️⃣ elapsedRealtime() 永远稳定
long start = SystemClock.elapsedRealtime();
// 做某件事
long cost = SystemClock.elapsedRealtime() - start;
✅ 不跳变
✅ 不回退
✅ 不怕 NTP
✅ 不怕用户改时间
四、车机开发中的典型错误(你一定见过)
❌ 错误用法
// 心跳包
if (System.currentTimeMillis() - lastTime > 5000) {
sendHeartbeat();
}
👉 时间一同步,心跳直接炸
✅ 正确用法
// 心跳
if (SystemClock.elapsedRealtime() - lastElapsed > 5000) {
sendHeartbeat();
}
五、两个 API 的"本质定义"
System.currentTimeMillis()
"人类世界的时间"
• 会被:
• 用户手动修改
• NTP 同步
• 运营商时间
• 时区变化
• 只适合:
• UI 显示
• 日志时间戳(非关键)
• 日历功能
SystemClock.elapsedRealtime()
"设备活了多久"
• 特点:
• 单调递增
• 不受任何外部影响
• 适合:
• 超时判断
• 性能统计
• 心跳
• 动画
• 车控指令间隔
六、车机开发的最佳实践(直接照抄)
✅ 通用规则
// 绝对不要这样写
if (System.currentTimeMillis() - last > timeout) ❌
// 永远这样写
if (SystemClock.elapsedRealtime() - last > timeout) ✅
✅ 日志 & 调试
Log.d(TAG, "cost=" +
(SystemClock.elapsedRealtime() - startTime) + "ms");
✅ 和系统时间配合(高阶)
long now;
if (isTimeSynced()) {
now = System.currentTimeMillis(); // 可信
} else {
now = estimateTimeByElapsed(); // 基于 uptime 推算
}
七、一张图记住区别
时间轴
--------------------------------------------------->
elapsedRealtime: 0ms → 100ms → 200ms → 永不回退 ✅
currentTimeMillis: 1970 → 2020 → 2026 → 可能跳变 ❌
八、总结一句话(给团队用)
System.currentTimeMillis() 是给人看的,
SystemClock.elapsedRealtime() 是给程序用的。
如果你愿意,我可以帮你:
• ✅ 审查你现有代码中 所有错误使用时间的地方
• ✅ 设计一套 车机时间可信度工具类
• ✅ 针对 HiCar / 仪表 / 诊断 / OTA 给出时间使用规范
你可以直接说:"帮我检查 XX 模块的时间用法"。