原创 Android 2025-06-13 17:32 北京
TrustedTime API 为您的应用提供可靠、安全的时间源。阅读本文,快速了解 TrustedTime API 的工作原理、用例和集成方法,让您的应用时间更精准,数据更可靠!
准确的时间对于各种应用功能而言至关重要,无论是日程安排、事件管理、事务日志记录,还是安全协议。但因为用户可以更改设备的时间设置,所以开发者可能需要一种比设备本地系统时间更准确的时间源。鉴于此,我们推出了 TrustedTime API,它利用 Google 的基础设施提供可信的时间戳,独立于设备上可能被篡改的本地时间设置。
TrustedTime 的
工作原理是什么?
新的 API 利用 Google 的安全基础设施,为您的应用提供可信的时间源。TrustedTime 会定期将其时钟与 Google 的服务器进行同步,这些服务器可以访问高度准确的时间源,因此您无需在每次想要了解当前网络时间时都发出服务器请求。此外,我们还集成了一个独特的模型来计算设备的时钟漂移,这将在网络同步之间的时间可能不准确时通知您。
为什么准确的时间源很重要?
许多应用依赖设备的时钟来实现各种功能。然而,用户可能会有意或无意地更改其设备的时间设置,从而影响应用获取到的时间。这可能导致以下问题:
数据不一致性:如果应用依赖于事件的时间顺序,则用户篡改设备时间可能导致数据损坏。TrustedTime 通过提供一个可信的时间源来降低这种风险。
安全漏洞:基于时间的安全措施,如一次性密码或定时访问控制,需要未经篡改的时间源才能生效。
时间安排失准:依赖于准确时间安排的应用,如日历或提醒事项应用,如果设备时钟 (例如 Unix 时间戳) 不准确,则可能会出现功能异常。
不准确的时间:设备的内部时钟受各种因素 (如温度、低电耗模式、电池电量等) 的影响,可能出现漂移,导致需要更高时间精度的应用出现问题。TrustedTime API 还提供针对时间戳的估计误差,以确保能够正确执行应用中具有严格时间要求的操作。
设备之间缺乏一致性:在多设备场景下,如游戏或协作应用中,设备间的时间差异可能会导致问题。TrustedTime API 有助于确保所有设备的时间保持一致,从而提升用户体验。
不必要的电量和数据消耗:TrustedTime 的设计目的在于,当应用需要获取当前时间时,提供比直接调用 NTP 服务器更加高效的方法。该 API 通过定期将其时钟与时间服务器同步,来避免重复请求网络的消耗。同步后的时间将作为参考,由 TrustedTime API 依据设备的内部时钟计算当前时间。这种方式降低了网络使用量,同时提高了需要频繁检查时间的应用的性能。
TrustedTime 用例
TrustedTime API 为提升应用的可靠性和安全性开辟了更多可能,其用例包括但不限于以下领域:
金融应用:即使设备处于离线状态,也能确保交易时间戳的准确性,防止欺诈和纠纷。
游戏:防止玩家篡改游戏时钟来获得不公平优势,实现公平竞技。
限时优惠:确保促销和优惠活动在正确的时间结束,不受用户设备设置的影响。
电子商务:准确跟踪订单处理和配送时间。
内容许可:对数字内容 (如租赁或订阅) 实施基于时间的限制。
IoT 设备:在多个设备之间同步时钟,以实现数据记录和控制的一致性。
工作效率应用:准确记录在离线状态下对云文档进行任何更改的时间。
开始使用 TrustedTime API
TrustedTime API 基于 Google Play 服务而构建,大多数 Android 开发者可以无缝集成。
最简单的集成方式是在应用生命周期的早期初始化 TrustedTimeClient,例如在 Application 类的 onCreate() 方法中进行初始化。以下示例使用 Hilt 进行依赖项注入,使时间客户端在整个应用的组件中可用。
[可选] 设置依赖项注入
// TrustedTimeClientAccessor.kt
import com.google.android.gms.tasks.Task
import com.google.android.gms.time.TrustedTimeClient
interface TrustedTimeClientAccessor {
fun createClient(): Task<TrustedTimeClient>
}
// TrustedTimeModule.kt
class TrustedTimeModule {
fun provideTrustedTimeClientAccessor(
Context context:
): TrustedTimeClientAccessor {
return object : TrustedTimeClientAccessor {
override fun createClient(): Task<TrustedTimeClient> {
return TrustedTime.createClient(context)
}
}
}
}
在应用生命周期的早期进行初始化
// TrustedTimeDemoApplication.kt
class TrustedTimeDemoApplication : Application() {
lateinit var trustedTimeClientAccessor: TrustedTimeClientAccessor
var trustedTimeClient: TrustedTimeClient? = null
private set
override fun onCreate() {
super.onCreate()
trustedTimeClientAccessor.createClient().addOnCompleteListener { task ->
if (task.isSuccessful) {
// Stash the client
trustedTimeClient = task.result
} else {
// Handle error, maybe retry later
val exception = task.exception
}
}
// To use Kotlin Coroutine, you can use the await() method,
// see https://developers.google.com/android/guides/tasks#kotlin_coroutine for more info.
}
}
NOTE: If you don't use dependency injection in your app. You can simply call
`TrustedTime.createClient(context)` instead of using a TrustedTimeClientAccessor.
在应用的任何位置使用 TrustedTimeClient
// Retrieve the TrustedTimeClient from your application class
val myApp = applicationContext as TrustedTimeDemoApplication
// In this example, System.currentTimeMillis() is used as a fallback if the
// client is null (i.e. client creation task failed) or when there is no time
// signal available. You may not want to do this if using the system clock is
// not suitable for your use case.
val currentTimeMillis =
myApp.trustedTimeClient?.computeCurrentUnixEpochMillis()
?: System.currentTimeMillis()
// trustedTimeClient.computeCurrentInstant() can be used if Instant is
// preferred to long for Unix epoch times and you are able to use the APIs.
在诸如 Activity 之类的短生命周期组件中使用
class MainActivity : AppCompatActivity() {
lateinit var trustedTimeAccessor: TrustedTimeAccessor
private var trustedTimeClient: TrustedTimeClient? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
trustedTimeAccessor.createClient().addOnCompleteListener { task ->
if (task.isSuccessful) {
// Stash the client
trustedTimeClient = task.result
} else {
// Handle error, maybe retry later or use another time source.
val exception = task.exception
}
}
}
private fun getCurrentTimeInMillis() : Long? {
return trustedTimeClient?.computeCurrentUnixEpochMillis()
}
}
TrustedTime API 的
可用性和局限性
TrustedTime API 在所有运行 Android 5 (Lollipop) 及以上版本且搭载了 Google Play 服务的设备上均可使用。您需要添加依赖项 com.google.android.gms:play-services-time:16.0.1 (或更高版本) 以访问新的 API。使用此 API 不需要额外的权限。但是,设备启动后 TrustedTime 需要连接互联网才能提供时间戳。如果设备启动后未连接到互联网,TrustedTime API 将无法返回时间戳。
需要注意的是,由于温度、低电耗模式和电池电量等因素的影响,设备的内部时钟可能会出现漂移。TrustedTime 并不能防止这种漂移,但其 API 为每个时间戳提供了一个误差估计。您可以使用这个估计值来判断时间戳的准确性是否符合应用的要求。虽然 TrustedTime 提高了用户篡改应用访问时间的难度,但它并不能完全保证安全性。用户仍有可能通过高级技术来篡改设备的时间。
后续步骤
您可以访问 Android 开发者官方网站了解有关 TrustedTime API 的更多信息。也欢迎您持续关注 "Android 开发者" 微信公众号,及时了解更多开发技术和产品更新等资讯动态!