我创建了一款安卓应用,用户可以在其中保存一些任务。这些任务保存在设备中,当用户联网时,任务将会同步到服务器上。
我需要知道用户保存任务的正确日期和时间。像Calendar.getInstance()
或new Date()
这样的代码会返回设备时间,如果设备时间不正确,任务就会以错误的日期保存。对于这个应用程序而言,离线工作非常重要。由于此应用程序的业务性质,用户故意更改设备时间是有可能的。
我创建了一款安卓应用,用户可以在其中保存一些任务。这些任务保存在设备中,当用户联网时,任务将会同步到服务器上。
我需要知道用户保存任务的正确日期和时间。像Calendar.getInstance()
或new Date()
这样的代码会返回设备时间,如果设备时间不正确,任务就会以错误的日期保存。对于这个应用程序而言,离线工作非常重要。由于此应用程序的业务性质,用户故意更改设备时间是有可能的。
所以,我最终得到了这样的情况:每个设备重新启动时,用户最多只会连接一次互联网。
当用户启动 (BOOT_COMPLETED BroadcastReceiver
) 或网络状态发生改变 (CONNECTIVITY_CHANGE 和 WIFI_STATE_CHANGED BroadcastReceiver
) 时,我尝试连接到 NTP 服务器,然后将日期和 SystemClock.elapsedRealtime()
存储在数据库中。之后,每当我需要正确的日期时,我只需获取新的 SystemClock.elapsedRealtime()
并计算此值与数据库中 elapsedRealtime 值之间的差异,并将该差异添加到存储在数据库中的日期中。
对于其他遇到同样问题的人,有一个强大的库叫做TrueTime。要使用它,请将其添加到您的项目依赖项中:
implementation 'com.github.instacart.truetime-android:library-extension-rx:3.5'
TrueTimeRx.build()
.withLoggingEnabled(true)
.withSharedPreferencesCache(this)
.initializeRx("1.us.pool.ntp.org")
.subscribeOn(Schedulers.io())
.subscribe(date -> Log.v("TrueTime", "TrueTime initialized, time: " + date),
throwable -> Log.e("TrueTime", "TrueTime exception: ", throwable)
);
使用方法:
if (TrueTimeRx.isInitialized()) {
Date reliableDateNow = TrueTimeRx.now();
// use the current date
}
工作原理:
它使用NTP协议从网络中仅初始化一次日期时间,并使用SystemClock.elapsedRealtime()计算日期时间。如果设备重新启动,它将使用指定的NTP服务器重新初始化时间。