From d234b75520b686eed649bf7eef122fc717d8c88c Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Tue, 14 Nov 2023 13:31:45 +0000 Subject: [PATCH 1/2] Fixes https://github.com/realm/realm-kotlin/issues/1564 usage of API introduced in Android 26 while minSDK is 16 --- CHANGELOG.md | 2 +- .../kotlin/internal/platform/SystemUtilsAndroid.kt | 12 ++++++++++++ .../kotlin/mongodb/internal/RealmSyncInitializer.kt | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d56a375bb1..87987c2e11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ * None. ### Fixed -* None. +* `RealmInstant.now` used an API (`java.time.Clock.systemUTC().instant()`) introduced in API 26, current minSDK is 16. (Issue [#1564](https://github.com/realm/realm-kotlin/issues/1564)) ### Compatibility * File format: Generates Realms with file format v23. diff --git a/packages/library-base/src/androidMain/kotlin/io/realm/kotlin/internal/platform/SystemUtilsAndroid.kt b/packages/library-base/src/androidMain/kotlin/io/realm/kotlin/internal/platform/SystemUtilsAndroid.kt index 949714d794..166b961a13 100644 --- a/packages/library-base/src/androidMain/kotlin/io/realm/kotlin/internal/platform/SystemUtilsAndroid.kt +++ b/packages/library-base/src/androidMain/kotlin/io/realm/kotlin/internal/platform/SystemUtilsAndroid.kt @@ -1,10 +1,13 @@ package io.realm.kotlin.internal.platform +import android.os.Build import io.realm.kotlin.internal.RealmInitializer +import io.realm.kotlin.internal.RealmInstantImpl import io.realm.kotlin.internal.interop.SyncConnectionParams import io.realm.kotlin.internal.util.Exceptions import io.realm.kotlin.log.LogLevel import io.realm.kotlin.log.RealmLogger +import io.realm.kotlin.types.RealmInstant import java.io.FileNotFoundException import java.io.InputStream @@ -36,3 +39,12 @@ public actual fun assetFileAsStream(assetFilename: String): InputStream = try { // Returns the default logger for the platform public actual fun createDefaultSystemLogger(tag: String, logLevel: LogLevel): RealmLogger = LogCatLogger(tag, logLevel) + +public actual fun currentTime(): RealmInstant { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val jtInstant = java.time.Clock.systemUTC().instant() + RealmInstantImpl(jtInstant.epochSecond, jtInstant.nano) + } else { + RealmInstantImpl(System.currentTimeMillis(), 0) + } +} diff --git a/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt b/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt index f5bed0c72c..081bea25af 100644 --- a/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt +++ b/packages/library-sync/src/androidMain/kotlin/io/realm/kotlin/mongodb/internal/RealmSyncInitializer.kt @@ -82,7 +82,7 @@ class RealmSyncInitializer : Initializer { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP /* 21 */) { val request = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP /* 23 */) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M /* 23 */) { request.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) } RealmLog.info("Register ConnectivityManager network callbacks") From 42a84fa6dc45b0c7189e0cb6b6dacf193baf8e8e Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Mon, 20 Nov 2023 22:53:19 +0000 Subject: [PATCH 2/2] Fixing implementation --- .../realm/kotlin/internal/platform/SystemUtils.kt | 1 + .../realm/kotlin/internal/platform/SystemUtils.kt | 12 ------------ .../kotlin/internal/platform/SystemUtilsJvm.kt | 13 +++++++++++++ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt index 010b1fa9a5..81ec75a5f1 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt @@ -137,6 +137,7 @@ public expect fun epochInSeconds(): Long /** * Returns a RealmInstant representing the time that has passed since the Unix epoch. + * For Android targets < API 26 there's no nano seconds precision. */ public expect fun currentTime(): RealmInstant diff --git a/packages/library-base/src/jvm/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt b/packages/library-base/src/jvm/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt index 5f042e6de1..1093a3f025 100644 --- a/packages/library-base/src/jvm/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt +++ b/packages/library-base/src/jvm/kotlin/io/realm/kotlin/internal/platform/SystemUtils.kt @@ -1,15 +1,12 @@ package io.realm.kotlin.internal.platform import io.realm.kotlin.internal.Constants.FILE_COPY_BUFFER_SIZE -import io.realm.kotlin.internal.RealmInstantImpl import io.realm.kotlin.internal.util.Exceptions -import io.realm.kotlin.types.RealmInstant import java.io.File import java.io.InputStream import java.io.OutputStream import java.security.DigestInputStream import java.security.MessageDigest -import java.time.Clock.systemUTC import java.util.concurrent.TimeUnit import kotlin.reflect.KMutableProperty1 import kotlin.reflect.KType @@ -24,15 +21,6 @@ public actual fun threadId(): ULong { public actual fun epochInSeconds(): Long = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) -/** -* Since internalNow() should only logically return a value after the Unix epoch, it is safe to create a RealmInstant -* without considering having to pass negative nanoseconds. -*/ -public actual fun currentTime(): RealmInstant { - val jtInstant = systemUTC().instant() - return RealmInstantImpl(jtInstant.epochSecond, jtInstant.nano) -} - public actual fun fileExists(path: String): Boolean = File(path).let { it.exists() && it.isFile } diff --git a/packages/library-base/src/jvmMain/kotlin/io/realm/kotlin/internal/platform/SystemUtilsJvm.kt b/packages/library-base/src/jvmMain/kotlin/io/realm/kotlin/internal/platform/SystemUtilsJvm.kt index f45a4b05fc..cedaba812b 100644 --- a/packages/library-base/src/jvmMain/kotlin/io/realm/kotlin/internal/platform/SystemUtilsJvm.kt +++ b/packages/library-base/src/jvmMain/kotlin/io/realm/kotlin/internal/platform/SystemUtilsJvm.kt @@ -1,12 +1,15 @@ package io.realm.kotlin.internal.platform import io.realm.kotlin.Realm +import io.realm.kotlin.internal.RealmInstantImpl import io.realm.kotlin.internal.interop.SyncConnectionParams import io.realm.kotlin.internal.util.Exceptions import io.realm.kotlin.log.LogLevel import io.realm.kotlin.log.RealmLogger +import io.realm.kotlin.types.RealmInstant import java.io.InputStream import java.net.URL +import java.time.Clock public actual val RUNTIME: SyncConnectionParams.Runtime = SyncConnectionParams.Runtime.JVM public actual val RUNTIME_VERSION: String = System.getProperty("java.version") @@ -27,3 +30,13 @@ public actual fun assetFileAsStream(assetFilename: String): InputStream { public actual fun createDefaultSystemLogger(tag: String, logLevel: LogLevel): RealmLogger = StdOutLogger(tag, logLevel) + +/** + * Since internalNow() should only logically return a value after the Unix epoch, it is safe to create a RealmInstant + * without considering having to pass negative nanoseconds. + */ +@Suppress("NewApi") // The implementation in SystemUtilsAndroid has a guard to only use systemUTC on API >= 26 +public actual fun currentTime(): RealmInstant { + val jtInstant = Clock.systemUTC().instant() + return RealmInstantImpl(jtInstant.epochSecond, jtInstant.nano) +}