diff --git a/.gitignore b/.gitignore index c407ae21..2cb59a23 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,146 @@ -.gradle -local.properties -.idea -.DS_Store +### Android-specific stuff +# Built application files +*.apk +*.ap_ +*.aab +*.apks + +# Files for the Dalvik VM +*.dex + +# Generated files bin/ gen/ + +# Local configuration file (sdk path, etc) +local.properties + +# Google/Firebase secrets +google-services.json + +### Windows template +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Linux template +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + *.iml -build/ -crashlytics-build.properties -com_crashlytics_export_strings.xml -captures/ -config.xml -secure.properties -tmp/ -build.properties +*.ipr +*.iws +/.idea/* + +# Exclude non-user-specific stuff +!.idea/.name +!.idea/codeInsightSettings.xml +!.idea/codeStyles/ +!.idea/copyright/ +!.idea/dataSources.xml +!.idea/detekt.xml +!.idea/encodings.xml +!.idea/externalDependencies.xml +!.idea/file.template.settings.xml +!.idea/fileTemplates/ +!.idea/icon.svg +!.idea/inspectionProfiles/ +!.idea/runConfigurations/ +!.idea/scopes/ +!.idea/vcs.xml + +### Kotlin template +# Compiled class file +*.class + +# Log file +*.log + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Gradle template +.gradle + +# Note that you may need to exclude by hand other folders +# named build if necessary (e.g., in src/) +**/build/ + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle/wrapper/gradle-wrapper.jar + +# Cache of project +.gradletasknamecache diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..4bec4ea8 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,117 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..471a9323 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index e468c1f4..34bb1721 100644 --- a/README.md +++ b/README.md @@ -2,26 +2,76 @@ ![TrueTime](truetime.png "TrueTime for Android") +*⚠️ See work in progress section below. TrueTime is undergoing some changes* + +---------------------------------------- + *Make sure to check out our counterpart too: [TrueTime](https://github.com/instacart/TrueTime.swift), an NTP library for Swift.* NTP client for Android. Calculate the date and time "now" impervious to manual changes to device clock time. -In certain applications it becomes important to get the real or "true" date and time. On most devices, if the clock has been changed manually, then a `new Date()` instance gives you a time impacted by local settings. +In certain applications it becomes important to get the real or "true" date and time. On most devices, if the clock has been changed manually, then a `Date()` instance gives you a time impacted by local settings. Users may do this for a variety of reasons, like being in different timezones, trying to be punctual by setting their clocks 5 – 10 minutes early, etc. Your application or service may want a date that is unaffected by these changes and reliable as a source of truth. TrueTime gives you that. You can read more about the use case in our [blog post](https://tech.instacart.com/truetime/). -In a [recent conference talk](https://vimeo.com/190922794), we explained how the full NTP implementation works with Rx. Check the [video](https://vimeo.com/190922794) and [slides](https://speakerdeck.com/kaushikgopal/learning-rx-by-example-2?slide=31) out for implementation details. +In a [conference talk](https://vimeo.com/190922794), we explained how the full NTP implementation works (with Rx). Check the [video](https://vimeo.com/190922794#t=1466s) and [slides](https://speakerdeck.com/kaushikgopal/learning-rx-by-example-2?slide=31) out for implementation details. + + +# Work in Progress 4.0 + +With the move to Kotlin & Coroutines TrueTime 4 was a [major overhaul](https://github.com/instacart/truetime-android/pull/129). We still haven't ported some of the additional bells & whistles. This section keeps track of those features (that will come in the near future). TrueTime is completely functional without these additional features, so feel free to start using it. + +Most of these todos should have corresponding "TODO" comments within the code. + +- [ ] Fix Jitpack import + +I may have busted the jitpack import. Got to fix this first. + +- [ ] Introduce a Cache provider + +* Add an `interface CacheProvider` so folks can inject in their preferred caching mechanisms +* Provide a default cache implementation (probably using the non-android version of [DataStore](https://developer.android.com/topic/libraries/architecture/datastore#kts)) +* ? Provide example of using this with a Database like Realm + +- [ ] Algorithmic improvements + +There are some exciting improvements that we have planned and use internally. Will have to upstream these changes (with a cleaner api + implementation) -Also, once we have this information it's valid until the next time you boot your device. This means if you enable the disk caching feature, after a single successful NTP request you can use the information on disk directly without ever making another network request. This applies even across application kills which can happen frequently if your users have a memory starved device. +- [ ] Move android dependency to separate package + +There's no reason for TrueTime (with the move to coroutines) to be an "android" library. It can be a pure kotlin lib. + +The only remaining dependency is `SystemClock` (which we should just have a provider for). + +- [ ] Utilize all ntp pool addresses from `TrueTimeParameters.ntpHostPool` + +We currently only take the first ntp host pool address from the supplied parameters. In the future, it would be nice to provide multiple ntp "pool" addresses like `time.google.com`, `time.apple.com` and utilize all of those to get the "best" value. + +- [ ] BootCompletedBroadcastReceiver sample + +Everytime a device is rebooted, the Truetime info is invalid. Previous libraries included an actual `BroadcastReceiver` but this is better handled by the application than the library. For safe measure, I'll include an example of how this can be done in case folks are curious. # Installation -[See the wiki instructions](https://github.com/instacart/truetime-android/wiki/How-to-use-this-library). +*⚠️ The Wiki has not been updated to the latest version of TrueTime* + +[See the wiki for full instructions](https://github.com/instacart/truetime-android/wiki/How-to-use-this-library). + +## Usage + +```kt +val trueTime = TrueTimeImpl() +trueTime.sync() +trueTime.now() +``` + +💥 # Wiki has a lot of useful information +*⚠️ The Wiki has not been updated to the latest version of TrueTime* Take a look at [the wiki sidebar](https://github.com/instacart/truetime-android/wiki) which should have a lot of useful information. # License diff --git a/app/build.gradle b/app/build.gradle index 0400ea89..596cc66c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,43 +1,56 @@ apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' android { compileSdkVersion rootProject.ext.compileSdkVersion + namespace 'com.instacart.sample' defaultConfig { - applicationId "com.instacart.library.truetime" + applicationId "com.instacart.truetime" minSdkVersion 14 targetSdkVersion rootProject.ext.targetSdkVersion versionCode rootProject.ext.versionCode versionName rootProject.ext.versionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + + buildFeatures { + viewBinding true + } } repositories { maven { url "https://jitpack.io" } + mavenCentral() } -ext { - butterknifeVersion = '8.8.1' -} dependencies { implementation project(path: ':library') - implementation project(path: ':library-extension-rx') -// compile 'com.github.instacart.truetime-android:library-extension-rx:master-SNAPSHOT' - - implementation 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' - implementation "com.jakewharton:butterknife:$butterknifeVersion" - annotationProcessor "com.jakewharton:butterknife-compiler:$butterknifeVersion" - implementation "io.reactivex.rxjava2:rxandroid:2.0.2" +// implementation project(path: ':library-extension-rx') + implementation 'com.github.instacart.truetime-android:library-extension-rx:3.5' + + implementation "org.jetbrains.kotlin:kotlin-stdlib" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" + + implementation 'androidx.appcompat:appcompat:1.5.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0' + + implementation "io.reactivex.rxjava2:rxandroid:2.1.1" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9e3fef82..d4b26f3a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,21 +1,23 @@ - + + android:name="com.instacart.sample.App" + android:theme="@style/AppTheme" + > - + + - \ No newline at end of file + diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 00000000..448d3865 Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/com/instacart/library/sample/App.java b/app/src/main/java/com/instacart/library/sample/App.java deleted file mode 100644 index 2b159e99..00000000 --- a/app/src/main/java/com/instacart/library/sample/App.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.instacart.library.sample; - -import android.app.Application; -import android.os.AsyncTask; -import android.util.Log; - -import com.instacart.library.truetime.TrueTime; -import com.instacart.library.truetime.TrueTimeRx; - -import java.io.IOException; -import java.util.Date; - -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.observers.DisposableSingleObserver; -import io.reactivex.schedulers.Schedulers; - -public class App extends Application { - - private static final String TAG = App.class.getSimpleName(); - - @Override - public void onCreate() { - super.onCreate(); - initRxTrueTime(); -// initTrueTime(); - } - - /** - * init the TrueTime using a AsyncTask. - */ - private void initTrueTime() { - new InitTrueTimeAsyncTask().execute(); - } - - // a little part of me died, having to use this - private class InitTrueTimeAsyncTask extends AsyncTask { - - protected Void doInBackground(Void... params) { - try { - TrueTime.build() - //.withSharedPreferences(SampleActivity.this) - .withNtpHost("time.google.com") - .withLoggingEnabled(false) - .withSharedPreferencesCache(App.this) - .withConnectionTimeout(3_1428) - .initialize(); - } catch (IOException e) { - e.printStackTrace(); - Log.e(TAG, "something went wrong when trying to initialize TrueTime", e); - } - return null; - } - } - - /** - * Initialize the TrueTime using RxJava. - */ - private void initRxTrueTime() { - DisposableSingleObserver disposable = TrueTimeRx.build() - .withConnectionTimeout(31_428) - .withRetryCount(100) - .withSharedPreferencesCache(this) - .withLoggingEnabled(true) - .initializeRx("time.google.com") - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeWith(new DisposableSingleObserver() { - @Override - public void onSuccess(Date date) { - Log.d(TAG, "Success initialized TrueTime :" + date.toString()); - } - - @Override - public void onError(Throwable e) { - Log.e(TAG, "something went wrong when trying to initializeRx TrueTime", e); - } - }); - } - - -} diff --git a/app/src/main/java/com/instacart/library/sample/Sample2Activity.java b/app/src/main/java/com/instacart/library/sample/Sample2Activity.java deleted file mode 100644 index f37abd93..00000000 --- a/app/src/main/java/com/instacart/library/sample/Sample2Activity.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.instacart.library.sample; - -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.util.Log; -import android.widget.Button; -import android.widget.TextView; -import android.widget.Toast; - -import com.instacart.library.truetime.TrueTimeRx; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; - -public class Sample2Activity - extends AppCompatActivity { - - @BindView(R.id.tt_btn_refresh) Button refreshBtn; - @BindView(R.id.tt_time_gmt) TextView timeGMT; - @BindView(R.id.tt_time_pst) TextView timePST; - @BindView(R.id.tt_time_device) TextView timeDeviceTime; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_sample); - - getSupportActionBar().setTitle("TrueTimeRx"); - - ButterKnife.bind(this); - refreshBtn.setEnabled(TrueTimeRx.isInitialized()); - } - - @OnClick(R.id.tt_btn_refresh) - public void onBtnRefresh() { - updateTime(); - } - - private void updateTime() { - if (!TrueTimeRx.isInitialized()) { - Toast.makeText(this, "Sorry TrueTime not yet initialized.", Toast.LENGTH_SHORT).show(); - return; - } - refreshBtn.setEnabled(true); - Date trueTime = TrueTimeRx.now(); - Date deviceTime = new Date(); - - Log.d("kg", - String.format(" [trueTime: %d] [devicetime: %d] [drift_sec: %f]", - trueTime.getTime(), - deviceTime.getTime(), - (trueTime.getTime() - deviceTime.getTime()) / 1000F)); - - timeGMT.setText(getString(R.string.tt_time_gmt, - _formatDate(trueTime, "yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("GMT")))); - timePST.setText(getString(R.string.tt_time_pst, - _formatDate(trueTime, "yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("GMT-07:00")))); - timeDeviceTime.setText(getString(R.string.tt_time_device, - _formatDate(deviceTime, - "yyyy-MM-dd HH:mm:ss", - TimeZone.getTimeZone("GMT-07:00")))); - } - - private String _formatDate(Date date, String pattern, TimeZone timeZone) { - DateFormat format = new SimpleDateFormat(pattern, Locale.ENGLISH); - format.setTimeZone(timeZone); - return format.format(date); - } -} diff --git a/app/src/main/java/com/instacart/library/sample/SampleActivity.java b/app/src/main/java/com/instacart/library/sample/SampleActivity.java deleted file mode 100644 index 81d59c39..00000000 --- a/app/src/main/java/com/instacart/library/sample/SampleActivity.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.instacart.library.sample; - -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.widget.Button; -import android.widget.TextView; -import android.widget.Toast; - -import com.instacart.library.truetime.TrueTime; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; - -public class SampleActivity - extends AppCompatActivity { - - @BindView(R.id.tt_btn_refresh) Button refreshBtn; - @BindView(R.id.tt_time_gmt) TextView timeGMT; - @BindView(R.id.tt_time_pst) TextView timePST; - @BindView(R.id.tt_time_device) TextView timeDeviceTime; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_sample); - ButterKnife.bind(this); - refreshBtn.setEnabled(TrueTime.isInitialized()); - } - - @OnClick(R.id.tt_btn_refresh) - public void onBtnRefresh() { - if (!TrueTime.isInitialized()) { - Toast.makeText(this, "Sorry TrueTime not yet initialized. Trying again.", Toast.LENGTH_SHORT).show(); - return; - } - - Date trueTime = TrueTime.now(); - Date deviceTime = new Date(); - - timeGMT.setText(getString(R.string.tt_time_gmt, - _formatDate(trueTime, "yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("GMT")))); - timePST.setText(getString(R.string.tt_time_pst, - _formatDate(trueTime, "yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("GMT-07:00")))); - timeDeviceTime.setText(getString(R.string.tt_time_device, - _formatDate(deviceTime, "yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("GMT-07:00")))); - } - - private String _formatDate(Date date, String pattern, TimeZone timeZone) { - DateFormat format = new SimpleDateFormat(pattern, Locale.ENGLISH); - format.setTimeZone(timeZone); - return format.format(date); - } - -} diff --git a/app/src/main/java/com/instacart/sample/App.kt b/app/src/main/java/com/instacart/sample/App.kt new file mode 100644 index 00000000..b61ee3f6 --- /dev/null +++ b/app/src/main/java/com/instacart/sample/App.kt @@ -0,0 +1,19 @@ +package com.instacart.sample + +import android.app.Application +import com.instacart.truetime.time.TrueTime +import com.instacart.truetime.time.TrueTimeImpl +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch + +@Suppress("unused") +class App : Application() { + +// val trueTime = TrueTimeImpl() + + override fun onCreate() { + super.onCreate() +// trueTime.sync() + } + +} diff --git a/app/src/main/java/com/instacart/sample/SampleActivity.kt b/app/src/main/java/com/instacart/sample/SampleActivity.kt new file mode 100644 index 00000000..2a6cc917 --- /dev/null +++ b/app/src/main/java/com/instacart/sample/SampleActivity.kt @@ -0,0 +1,124 @@ +package com.instacart.sample + +import android.annotation.SuppressLint +import android.os.Build +import android.os.Bundle +import android.util.Log +import androidx.annotation.RequiresApi +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope +import com.instacart.library.truetime.TrueTimeRx +import com.instacart.sample.databinding.ActivitySampleBinding +import com.instacart.truetime.time.TrueTime +import com.instacart.truetime.time.TrueTimeImpl +import com.instacart.truetime.time.TrueTimeParameters +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.schedulers.Schedulers +import kotlinx.coroutines.* +import java.time.Instant +import java.time.ZoneId +import java.time.format.DateTimeFormatter +import java.util.Date +import java.util.Timer +import kotlin.concurrent.schedule + +@SuppressLint("SetTextI18n") +@RequiresApi(Build.VERSION_CODES.O) +class SampleActivity : AppCompatActivity() { + + private lateinit var binding: ActivitySampleBinding + private val disposables = CompositeDisposable() + + private lateinit var sampleTrueTime: TrueTime + private lateinit var job: Job + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivitySampleBinding.inflate(layoutInflater) + setContentView(binding.root) + + supportActionBar?.title = "True Time Demo" +// (application as App).trueTime.now() + + binding.btnRefresh.setOnClickListener { refreshTime() } + } + + override fun onDestroy() { + super.onDestroy() + disposables.clear() + job.cancel() + } + + private fun refreshTime() { + binding.deviceTime.text = "Device Time: (loading...)" + + kickOffTruetimeCoroutines() + kickOffTrueTimeRx() + + binding.deviceTime.text = "Device Time: ${formatDate(Date())}" + } + + private fun kickOffTruetimeCoroutines() { + + binding.truetimeNew.text = "(Coroutines): (loading...)" + + if (::job.isInitialized) job.cancel() + + if (!::sampleTrueTime.isInitialized) { + val params = TrueTimeParameters.Builder() + .ntpHostPool(arrayListOf("time.apple.com")) + .connectionTimeoutInMillis(31428) + .syncIntervalInMillis(1_000) + .retryCountAgainstSingleIp(3) + .returnSafelyWhenUninitialized(false) + .serverResponseDelayMaxInMillis(900) // this value is pretty high (coding on a plane) + .buildParams() + + sampleTrueTime = TrueTimeImpl(params, listener = TrueTimeLogEventListener()) + } + + job = sampleTrueTime.sync() + + lifecycleScope.launch { + while (!sampleTrueTime.hasTheTime()) { + delay(500) + } + + binding.truetimeNew.text = "(Coroutines): ${formatDate(sampleTrueTime.now())}" + } + + if (false) { + Timer("Kill Sync Job", false).schedule(12_000) { + job.cancel() + } + } + } + + private fun kickOffTrueTimeRx() { + binding.truetimeLegacy.text = "(Rx) : (loading...)" + + val d = TrueTimeRx() + .withConnectionTimeout(31428) + .withRetryCount(100) +// .withSharedPreferencesCache(this) + .withLoggingEnabled(false) + .initializeRx("time.google.com") + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ date -> + binding.truetimeLegacy.text = "(Rx) : ${formatDate(date)}" + }, { + Log.e("Demo", "something went wrong when trying to initializeRx TrueTime", it) + }) + + disposables.add(d) + } + + private fun formatDate(date: Date): String { + return Instant + .ofEpochMilli(date.time) + .atZone(ZoneId.of("America/Los_Angeles")) + .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + } +} diff --git a/app/src/main/java/com/instacart/sample/TrueTimeLogEventListener.kt b/app/src/main/java/com/instacart/sample/TrueTimeLogEventListener.kt new file mode 100644 index 00000000..ca5defb2 --- /dev/null +++ b/app/src/main/java/com/instacart/sample/TrueTimeLogEventListener.kt @@ -0,0 +1,65 @@ +package com.instacart.sample + +import android.util.Log +import com.instacart.truetime.TrueTimeEventListener +import com.instacart.truetime.time.TrueTimeParameters +import java.net.InetAddress +import java.util.Date + +class TrueTimeLogEventListener: TrueTimeEventListener { + override fun initialize(params: TrueTimeParameters) { + Log.v("TrueTime4", "initialize call performed with $params") + } + + override fun initializeSuccess(ntpResult: LongArray) { + Log.i("TrueTime4", "came back successfully with $ntpResult") + } + + override fun initializeFailed(e: Exception) { + Log.e("TrueTime4", "initialization call failed with a generic exception", e) + } + + override fun nextInitializeIn(delayInMillis: Long) { + Log.v("TrueTime4", " next initialization call will be made in $delayInMillis ms") + } + + override fun resolvedNtpHostToIPs(ntpHost: String, ipList: List) { + Log.v("TrueTime4", "resolved NTP pool host address $ntpHost to the list of IP addresses $ipList") + } + + override fun lastSntpRequestAttempt(ipHost: InetAddress) { + Log.v("TrueTime4", "This is the last SNTP request attempt to $ipHost") + } + + override fun sntpRequestFailed(e: Exception) { + Log.e("TrueTime4", "SNTP request failed", e) + } + + override fun syncDispatcherException(t: Throwable) { + Log.e("TrueTime4", "CoroutineDispatcher exception from TrueTime sync call", t) + } + + override fun sntpRequest(address: InetAddress) { + Log.v("TrueTime4 SNTP", "SNTP request to $address") + } + + override fun sntpRequestSuccessful(address: InetAddress) { + Log.v("TrueTime4 SNTP", "SNTP Request to $address came back successfully") + } + + override fun sntpRequestFailed(address: InetAddress, e: Exception) { +// Log.e("TrueTime4 SNTP", "SNTP Request to $ntpHost failed", e) + } + + override fun storingTrueTime(ntpResult: LongArray) { + Log.v("TrueTime4 TimeKeeper", "TimeKeeper storing time $ntpResult") + } + + override fun returningTrueTime(trueTime: Date) { + Log.v("TrueTime4 TimeKeeper", "returning TrueTime $trueTime" ) + } + + override fun returningDeviceTime() { + Log.v("TrueTime4 TimeKeeper", "returning Device Time" ) + } +} diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..2408e30d --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..c1b0c5de --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/layout/activity_sample.xml b/app/src/main/res/layout/activity_sample.xml index 13b52e99..b697b86e 100644 --- a/app/src/main/res/layout/activity_sample.xml +++ b/app/src/main/res/layout/activity_sample.xml @@ -1,77 +1,65 @@ - - - - - - - - -