Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions KotlinSample/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,6 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)

implementation("com.google.android.gms:play-services-time:16.0.1")
}
7 changes: 3 additions & 4 deletions KotlinSample/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:name=".MyApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.KotlinSample"
tools:targetApi="31">
android:theme="@style/Theme.KotlinSample">
<activity
android:name=".MainActivity"
android:exported="true">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
package com.example.kotlinsample

import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.kotlinsample.TrustedTimeClientAccessor.getTrustedTimeClientTask
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.gms.time.TrustedTimeClient
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter


class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -16,5 +26,56 @@ class MainActivity : AppCompatActivity() {
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}

// Use TrustedTimeClient anywhere in your app
findViewById<View>(R.id.button1).setOnClickListener(View.OnClickListener { v ->
// Retrieve the TrustedTimeClient from your application class
val myApp = applicationContext as MyApp

// 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()
val instant = myApp.trustedTimeClient!!.computeCurrentInstant()
// trustedTimeClient.computeCurrentInstant() can be used if Instant is
// preferred to long for Unix epoch times and you are able to use the APIs.
val currentTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault())

val formattedString =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(currentTime)
Log.d("MainActivity", "currentTimeMillis: $currentTimeMillis")
Log.d("MainActivity", "formattedString: $formattedString")

findViewById<TextView>(R.id.textView1).text = "" + currentTimeMillis
findViewById<TextView>(R.id.textView2).text = formattedString
})

// Use in short-lived components like Activity
findViewById<View>(R.id.button2).setOnClickListener(View.OnClickListener { v ->
getTrustedTimeClientTask(this).addOnCompleteListener(OnCompleteListener { task ->
if (task.isSuccessful) {
val trustedTimeClient: TrustedTimeClient = task.getResult()!!
val currentTimeMillis = trustedTimeClient.computeCurrentUnixEpochMillis()
val instant = trustedTimeClient.computeCurrentInstant()
val currentTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault())

val formattedString =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(currentTime)
Log.d("MainActivity", "currentTimeMillis: $currentTimeMillis")
Log.d("MainActivity", "formattedString: $formattedString")

findViewById<TextView>(R.id.textView1).text = "" + currentTimeMillis
findViewById<TextView>(R.id.textView2).text = formattedString
} else {
// Handle error
// jp) エラーになるケースの具体例がわからないため、予期せぬ問題としてクラッシュさせる
// en) Since I do not know the specific example of the case where an error occurs, I crash as an unexpected problem.
val exception = task.exception
Log.e("MainActivity", "error", exception)
throw IllegalStateException("TrustedTimeClient is not available", exception)
}
})
})
}
}
28 changes: 28 additions & 0 deletions KotlinSample/app/src/main/java/com/example/kotlinsample/MyApp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.kotlinsample

import android.app.Application
import android.util.Log
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.gms.time.TrustedTimeClient

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

override fun onCreate() {
super.onCreate()

TrustedTimeClientAccessor.getTrustedTimeClientTask(this)
.addOnCompleteListener(OnCompleteListener { task ->
if (task.isSuccessful) {
trustedTimeClient = task.getResult()
} else {
// Handle error
// jp) エラーになるケースの具体例がわからないため、予期せぬ問題としてクラッシュさせる
// en) Since I do not know the specific example of the case where an error occurs, I crash as an unexpected problem.
val exception = task.exception
Log.e("MyApp", "error", exception)
throw IllegalStateException("TrustedTimeClient is not available", exception)
}
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.example.kotlinsample

import android.content.Context
import com.google.android.gms.tasks.Task
import com.google.android.gms.time.TrustedTime
import com.google.android.gms.time.TrustedTimeClient
import java.lang.reflect.Modifier.SYNCHRONIZED

object TrustedTimeClientAccessor {
@Volatile
private var trustedTimeClientTask: Task<TrustedTimeClient>? = null

/**
* @see [Double-checked_locking](https://en.wikipedia.org/wiki/Double-checked_locking.Usage_in_Java)
* @see [Singleton_pattern](https://en.wikipedia.org/wiki/Singleton_pattern)
*/
fun getTrustedTimeClientTask(context: Context): Task<TrustedTimeClient> {
if (trustedTimeClientTask != null) {
return trustedTimeClientTask!!
} else {
synchronized(TrustedTimeClientAccessor::class.java) {
if (trustedTimeClientTask == null) {
trustedTimeClientTask = TrustedTime.createClient(context)
}
return trustedTimeClientTask!!
}
}
}
}
31 changes: 23 additions & 8 deletions KotlinSample/app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">

<TextView
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:text="test 1" />

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test 2" />

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
Binary file added KotlinSample/img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.