Skip to content

TrustedTime API: A Reliable Approach to Time Keeping in Android Apps

Today, we’ll explore the TrustedTime API, a new API introduced to ensure accurate and secure timekeeping in Android apps. It helps apps prevent time tampering, ensuring that system time remains reliable for critical operations.

Why TrustedTime API?

Time manipulation can lead to security vulnerabilities, affecting authentication mechanisms, digital signatures, and event logging. The TrustedTime API provides apps with a tamper-resistant time source that remains consistent even if the system clock is changed by the user.

How It Works

The TrustedTime API sources time from secure sources such as GPS, NTP (Network Time Protocol), and carrier networks. It provides a monotonic and verifiable timestamp that apps can use instead of relying solely on System.currentTimeMillis().

Add the Dependency

First, include the TrustedTime API dependency in your build.gradle file:

implementation("com.google.android.gms:play-services-time:16.0.1")

This ensures your app can access the API via Google Play services.

Initialize TrustedTime Early

The TrustedTimeClient should be initialized early in your app’s lifecycle, preferably in the Application class.

class MyApp : Application() {
    private var trustedTimeClient: TrustedTimeClient? = null

    override fun onCreate() {
        super.onCreate()
        TrustedTime.createClient(this)
            .addOnSuccessListener { client -> trustedTimeClient = client }
            .addOnFailureListener { exception -> 
                Log.e("TrustedTime", "Failed to create client", exception)
            }
    }

    fun getTrustedTimeClient(): TrustedTimeClient? = trustedTimeClient
}

This initializes the TrustedTimeClient once and makes it available throughout the app.

Retrieve a Trusted Timestamp

Once initialized, you can fetch the current trusted time anywhere in your app. The API provides a secure timestamp that falls back to the system clock if no verified time is available.

val trustedTimeClient = (applicationContext as MyApp).getTrustedTimeClient()
val currentTimeMillis = trustedTimeClient?.computeCurrentUnixEpochMillis()
    ?: System.currentTimeMillis()

Log.d("TrustedTime", "Current Trusted Time: $currentTimeMillis")

Using TrustedTime in Activities

If you’re working within an Activity or Fragment, you can create a new TrustedTimeClient instance when needed:

class MainActivity : AppCompatActivity() {
    private var trustedTimeClient: TrustedTimeClient? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        TrustedTime.createClient(this)
            .addOnSuccessListener { client -> trustedTimeClient = client }
            .addOnFailureListener { exception -> 
                Log.e("TrustedTime", "Failed to create client", exception)
            }
    }

    private fun getCurrentTrustedTime(): Long? {
        return trustedTimeClient?.computeCurrentUnixEpochMillis()
    }
}

Using TrustedTime in Compose

If you need to access TrustedTimeClient in a Composable, you can use LaunchedEffect to fetch it in the background without blocking the UI.

@Composable
fun TrustedTimeScreen() {
    val context = LocalContext.current.applicationContext as MyApp
    var trustedTime by remember { mutableStateOf<Long?>(null) }

    LaunchedEffect(Unit) {
        trustedTime = context.getTrustedTimeClient()?.computeCurrentUnixEpochMillis()
    }

    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = trustedTime?.toString() ?: "Fetching trusted time...",
            style = MaterialTheme.typography.bodyLarge
        )
    }
}

Handling Trusted Time Availability

Since TrustedTime requires an internet connection after device startup, it’s important to handle cases where a trusted timestamp isn’t available:

if (trustedTimeClient?.hasReliableTime() == true) {
    val trustedTime = trustedTimeClient?.computeCurrentUnixEpochMillis()
    Log.d("TrustedTime", "Using trusted time: $trustedTime")
} else {
    Log.w("TrustedTime", "Trusted time unavailable, falling back to system time")
}

Limitations

The TrustedTime API ensures reliable timekeeping on Android devices running Google Play services (Android 5.0 and above), but it comes with certain limitations. Since it requires an internet connection after a device boots up, timestamps won’t be available if the device hasn’t connected online. Additionally, while TrustedTime helps prevent manual time manipulation, it does not eliminate clock drift, which can still occur due to environmental factors like temperature, battery level, or doze mode.

To mitigate this, the API provides error estimates that developers can use to assess the reliability of timestamps. Though it enhances security, TrustedTime is not foolproof—sophisticated tampering methods can still manipulate time-dependent operations, so apps requiring absolute accuracy should implement additional safeguards.

While the API requires an internet connection after boot to retrieve timestamps, it does cache the last known trusted time when the device goes offline. This means apps can still access a recently verified timestamp, but its accuracy depends on when the last sync occurred.


I hope you enjoyed this article, feel free to contact me if you need anything. See you next time.

Photo by Aron Visuals on Unsplash

https://android-developers.googleblog.com/2025/02/trustedtime-api-introducing-reliable-approach-to-time-keeping-for-apps.html