TrustedTime APIで信頼できる時刻を取得する
公式ブログで紹介されていた TrustedTime API が気になったので、実際に試してみました。こちらのAPIを使うと端末時間をユーザーが変更しても信頼できる時刻を取得できるとのことです。
ライブラリ追加
implementation("com.google.android.gms:play-services-time:16.0.1")
クライアント取得
まずはメインとなるクライアントを取得する必要があります。TrustedTime.createClient
から取得できます。
TrustedTime.createClient(context).addOnCompleteListener { task ->
if (task.isSuccessful) {
// 成功したときにTrustedTimeClientオブジェクトを保持
trustedTimeClient = task.result
} else {
// 取得失敗したときのエラー
}
}
play-servicesでよくある Task
を使ったものになります。 kotlinx-coroutines-play-services
を使うと Coroutines でも使用できます。
時間を取得する
Unixタイムのミリ秒として以下で取得できます。
trustedTimeClient.computeCurrentUnixEpochMillis()
他にも java.time.Instant
を返すメソッドもあります。
trustedTimeClient.computeCurrentInstant()
端末の時間を変更していても、ほぼ正しい時間を返してくれます。(誤差はあるかもです)
これだけなので、使い方としてはシンプルかなと思います。
TimeSignalについて
基本的に使うことはないのですが、 TimeSignal
というものがあり、以下で取得できます。
trustedTimeClient.latestTimeSignal
TimeSignal
は時刻同期したときのものを表していて、 latestTimeSignal
は最新のものになります。
時刻同期するイベントを以下のように監視することもできます。
trustedTimeClient.addTimeSignalListener { timeSignal ->
// ..
}
(これ1時間近く待ってみたのですが、ぼくは観測できなかったです)
上記で紹介した、 computeCurrentUnixEpochMillis
と computeCurrentInstant
は内部では 最新の TimeSignal
から取得されてるものになります。TimeSignal
からは推定される誤差なども取得できたりします。
制限事項
公式ブログに書いてあるとおり、ネットワーク接続が必要になります。また、デバイスの内部クロックなどからズレる可能性はあるとのことです。
試しに、1度もネットワーク接続していないエミュレータを使って試したところ、 TrustedTime.createClient
の結果が以下のようなエラーになりました。
com.google.android.gms.common.api.ApiException: 17: API: TrustedTime.API is not available on this device. Connection failed with: ConnectionResult{statusCode=DEVELOPER_ERROR, resolution=null, message=null}
そのあとネットワーク繋いでみたのですが、すぐには復帰しないようでして、結構長い時間待たないとダメそうでした。
なので、確実に取得できるわけでものないので、フォールバックとして通常のシステム時刻を返すような処理を入れおくのが安全です。