diff --git a/app/build.gradle b/app/build.gradle index ee3bb251..237ebe43 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -250,6 +250,10 @@ dependencies { implementation "com.github.lisawray.groupie:groupie:$groupie_version" implementation "com.github.lisawray.groupie:groupie-viewbinding:$groupie_version" + // Kronos ntp clock + def kronos_latest_version = "0.0.1-alpha09" + implementation "com.lyft.kronos:kronos-android:$kronos_latest_version" + //// TEST RELATED DEPENDENCIES testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:$kotlin_version" diff --git a/app/src/main/java/org/covidwatch/android/BaseCovidWatchApplication.kt b/app/src/main/java/org/covidwatch/android/BaseCovidWatchApplication.kt index f7b01472..33a49aec 100644 --- a/app/src/main/java/org/covidwatch/android/BaseCovidWatchApplication.kt +++ b/app/src/main/java/org/covidwatch/android/BaseCovidWatchApplication.kt @@ -2,6 +2,7 @@ package org.covidwatch.android import android.app.Application import kotlinx.coroutines.GlobalScope +import org.covidwatch.android.data.NtpTime import org.covidwatch.android.di.appModule import org.covidwatch.android.di.flavorSpecificModule import org.covidwatch.android.domain.ProvideDiagnosisKeysUseCase @@ -18,6 +19,7 @@ open class BaseCovidWatchApplication : Application() { private val updateRegionsUseCase: UpdateRegionsUseCase by inject() private val removeOldExposuresUseCase: RemoveOldDataUseCase by inject() private val provideDiagnosisKeysUseCase: ProvideDiagnosisKeysUseCase by inject() + private val ntpTime: NtpTime by inject() override fun onCreate() { super.onCreate() @@ -36,5 +38,7 @@ open class BaseCovidWatchApplication : Application() { launchUseCase(removeOldExposuresUseCase) launchUseCase(updateRegionsUseCase) } + + ntpTime.syncInBackground() } } diff --git a/app/src/main/java/org/covidwatch/android/data/NtpTime.kt b/app/src/main/java/org/covidwatch/android/data/NtpTime.kt new file mode 100644 index 00000000..e05c72e9 --- /dev/null +++ b/app/src/main/java/org/covidwatch/android/data/NtpTime.kt @@ -0,0 +1,19 @@ +package org.covidwatch.android.data + +import android.content.Context +import com.lyft.kronos.AndroidClockFactory +import com.lyft.kronos.KronosClock +import java.time.Instant +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.ZoneId + +class NtpTime (context : Context) { + private val kronosClock : KronosClock = AndroidClockFactory.createKronosClock(context) + + fun currentTimeMillis() : Long = kronosClock.getCurrentTimeMs() + + fun syncInBackground() = kronosClock.syncInBackground() + + fun nowAsInstant() : Instant = Instant.ofEpochMilli(currentTimeMillis()) +} diff --git a/app/src/main/java/org/covidwatch/android/di/AppModule.kt b/app/src/main/java/org/covidwatch/android/di/AppModule.kt index 7ba96ab5..09b8f9ea 100644 --- a/app/src/main/java/org/covidwatch/android/di/AppModule.kt +++ b/app/src/main/java/org/covidwatch/android/di/AppModule.kt @@ -181,6 +181,10 @@ val appModule = module { ) } + single { + NtpTime(androidApplication()) + } + factory { ProvideDiagnosisKeysUseCase( workManager = get(), diff --git a/app/src/main/java/org/covidwatch/android/extension/Instant.kt b/app/src/main/java/org/covidwatch/android/extension/Instant.kt new file mode 100644 index 00000000..e152a1d2 --- /dev/null +++ b/app/src/main/java/org/covidwatch/android/extension/Instant.kt @@ -0,0 +1,8 @@ +package org.covidwatch.android.extension + +import java.time.Instant +import java.time.temporal.ChronoUnit + +fun Instant.plusDays(daysToAdd : Long) : Instant = plus(daysToAdd, ChronoUnit.DAYS) + +fun Instant.minusDays(daysToSubtract : Long) : Instant = minus(daysToSubtract, ChronoUnit.DAYS) diff --git a/app/src/main/java/org/covidwatch/android/ui/reporting/VerifyPositiveDiagnosisFragment.kt b/app/src/main/java/org/covidwatch/android/ui/reporting/VerifyPositiveDiagnosisFragment.kt index 038e05d3..279d2658 100644 --- a/app/src/main/java/org/covidwatch/android/ui/reporting/VerifyPositiveDiagnosisFragment.kt +++ b/app/src/main/java/org/covidwatch/android/ui/reporting/VerifyPositiveDiagnosisFragment.kt @@ -14,19 +14,21 @@ import com.google.android.material.datepicker.CalendarConstraints import com.google.android.material.datepicker.MaterialDatePicker import com.google.android.material.textfield.TextInputLayout import org.covidwatch.android.R +import org.covidwatch.android.data.NtpTime import org.covidwatch.android.databinding.FragmentVerifyPositiveDiagnosisBinding +import org.covidwatch.android.extension.minusDays import org.covidwatch.android.extension.observe import org.covidwatch.android.extension.observeEvent import org.covidwatch.android.extension.observeNullableEvent -import org.covidwatch.android.extension.toInstant import org.covidwatch.android.ui.BaseViewModelFragment +import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.stateViewModel -import java.time.LocalDate class VerifyPositiveDiagnosisFragment : BaseViewModelFragment() { override val viewModel: VerifyPositiveDiagnosisViewModel by stateViewModel() + private val ntpTime: NtpTime by inject() override fun bind( inflater: LayoutInflater, @@ -119,15 +121,16 @@ class VerifyPositiveDiagnosisFragment : val builder = MaterialDatePicker.Builder.datePicker() val constraints = CalendarConstraints.Builder() - val twoWeeksAgo = LocalDate.now().plusDays(-14).toInstant() - .toEpochMilli() + val twoWeeksAgo = ntpTime.nowAsInstant().minusDays(14).toEpochMilli() // Day in the past or 14 days back val fromWhen = dayInPast ?: twoWeeksAgo - val untilNow = LocalDate.now().toInstant().toEpochMilli() + val untilNow = ntpTime.currentTimeMillis() - constraints.setValidator(BaseDateValidator { it in fromWhen..untilNow }) + constraints + .setValidator(BaseDateValidator { it in fromWhen..untilNow }) + .setOpenAt(untilNow) val datePicker = builder .setSelection(selection)