diff --git a/datalayer/phone/api/current.api b/datalayer/phone/api/current.api index 13b413c06a..b8ff0892ea 100644 --- a/datalayer/phone/api/current.api +++ b/datalayer/phone/api/current.api @@ -9,6 +9,12 @@ package com.google.android.horologist.datalayer.phone { method public suspend Object? installOnNode(String nodeId, kotlin.coroutines.Continuation); method @CheckResult public suspend Object? startCompanion(String nodeId, kotlin.coroutines.Continuation); property public kotlinx.coroutines.flow.Flow> connectedAndInstalledNodes; + field public static final com.google.android.horologist.datalayer.phone.PhoneDataLayerAppHelper.Companion Companion; + } + + public static final class PhoneDataLayerAppHelper.Companion { + method public com.google.android.horologist.datalayer.phone.Version getRequiredCompanionVersion(); + property public final com.google.android.horologist.datalayer.phone.Version RequiredCompanionVersion; } public final class PhoneDataLayerListenerService extends com.google.android.horologist.data.apphelper.DataLayerAppHelperService { @@ -18,11 +24,16 @@ package com.google.android.horologist.datalayer.phone { } public final class Version implements java.lang.Comparable { - ctor public Version(String inputVersion); method public int compareTo(com.google.android.horologist.datalayer.phone.Version other); - method public String getVersion(); - method public void setVersion(String); - property public final String version; + method public java.util.List component1(); + method public com.google.android.horologist.datalayer.phone.Version copy(java.util.List inputVersion); + method public java.util.List getInputVersion(); + property public final java.util.List inputVersion; + field public static final com.google.android.horologist.datalayer.phone.Version.Companion Companion; + } + + public static final class Version.Companion { + method public com.google.android.horologist.datalayer.phone.Version? parse(String version); } } diff --git a/datalayer/phone/build.gradle.kts b/datalayer/phone/build.gradle.kts index c21854f38a..65fe5693c8 100644 --- a/datalayer/phone/build.gradle.kts +++ b/datalayer/phone/build.gradle.kts @@ -97,6 +97,9 @@ dependencies { implementation(libs.kotlinx.coroutines.playservices) implementation(libs.androidx.lifecycle.runtime) implementation(libs.androidx.wear.remote.interactions) + + testImplementation(libs.junit) + testImplementation(libs.truth) } tasks.withType().configureEach { diff --git a/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/PhoneDataLayerAppHelper.kt b/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/PhoneDataLayerAppHelper.kt index dfd7a8ec39..ae039b9c34 100644 --- a/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/PhoneDataLayerAppHelper.kt +++ b/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/PhoneDataLayerAppHelper.kt @@ -112,24 +112,19 @@ public class PhoneDataLayerAppHelper( * Checks that the companion app supports deep linking to Tile editor setting. */ public fun checkCompanionVersionSupportTileEditing(): AppHelperResultCode? { - try { + return try { val packageInfo: PackageInfo = context.packageManager.getPackageInfo("com.google.android.apps.wear.companion", 0) val version = packageInfo.versionName - if (Version(version).compareTo(Version("2.1.0.576785526")) >= 0) { - return AppHelperResultCode.APP_HELPER_RESULT_SUCCESS + val companionVersion = Version.parse(version) + if (companionVersion != null && companionVersion >= RequiredCompanionVersion) { + AppHelperResultCode.APP_HELPER_RESULT_SUCCESS } else { - return AppHelperResultCode.APP_HELPER_RESULT_INVALID_COMPANION - } - } catch (ex: Exception) { - when (ex) { - is PackageManager.NameNotFoundException, is IllegalArgumentException -> { - return AppHelperResultCode.APP_HELPER_RESULT_NO_COMPANION_FOUND - } - - else -> throw ex + AppHelperResultCode.APP_HELPER_RESULT_INVALID_COMPANION } + } catch (nnfe: PackageManager.NameNotFoundException) { + AppHelperResultCode.APP_HELPER_RESULT_NO_COMPANION_FOUND } } @@ -146,4 +141,8 @@ public class PhoneDataLayerAppHelper( companionPackage } } + + public companion object { + public val RequiredCompanionVersion: Version = Version.parse("2.1.0.576785526")!! + } } diff --git a/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/Version.kt b/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/Version.kt index b18f982e2c..8f939d7ba4 100644 --- a/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/Version.kt +++ b/datalayer/phone/src/main/java/com/google/android/horologist/datalayer/phone/Version.kt @@ -16,28 +16,26 @@ package com.google.android.horologist.datalayer.phone -import kotlin.math.max +public data class Version internal constructor(val inputVersion: List) : + Comparable { -public class Version(inputVersion: String) : Comparable { + public override fun compareTo(other: Version): Int { + inputVersion.zip(other.inputVersion).forEach { (t, o) -> + val comparison = t.compareTo(o) + if (comparison != 0) { + return comparison + } + } + return inputVersion.size.compareTo(other.inputVersion.size) + } - public var version: String + public companion object { + public fun parse(version: String): Version? { + if (!version.matches("[0-9]+(\\.[0-9]+)*".toRegex())) { + return null + } - public override fun compareTo(other: Version): Int = - (split() to other.split()).let { (thisParts, thatParts) -> - val length = max(thisParts.size, thatParts.size) - for (i in 0 until length) { - val thisPart = if (i < thisParts.size) thisParts[i].toInt() else 0 - val thatPart = if (i < thatParts.size) thatParts[i].toInt() else 0 - if (thisPart < thatPart) return -1 - if (thisPart > thatPart) return 1 + return Version(version.split(".").toList().map { it.toInt() }) } - 0 } - - init { - require(inputVersion.matches("[0-9]+(\\.[0-9]+)*".toRegex())) { "Invalid version format" } - version = inputVersion } -} - -private fun Version.split() = version.split(".").toTypedArray() diff --git a/datalayer/phone/src/test/java/com/google/android/horologist/datalayer/phone/VersionTest.kt b/datalayer/phone/src/test/java/com/google/android/horologist/datalayer/phone/VersionTest.kt new file mode 100644 index 0000000000..3b15a3c610 --- /dev/null +++ b/datalayer/phone/src/test/java/com/google/android/horologist/datalayer/phone/VersionTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.horologist.datalayer.phone + +import com.google.common.truth.Truth.assertThat +import org.junit.Test + +class VersionTest { + @Test + fun testValid() { + assertThat(Version.parse("1.2")!!.inputVersion).containsExactly(1, 2).inOrder() + assertThat(Version.parse("2.1.0.576785526")!!.inputVersion).containsExactly( + 2, + 1, + 0, + 576785526, + ).inOrder() + } + + @Test + fun testNotValid() { + assertThat(Version.parse("XYZ")).isNull() + assertThat(Version.parse("2.1.0.X")).isNull() + } + + @Test + fun testComparison() { + val known = Version.parse("2.1.0.576785526") + val knownPlusPatch = Version.parse("2.1.1") + val knownPlusMinor = Version.parse("2.2.0.576785526") + val knownMinorOnly = Version.parse("2.1") + val knownPlusPatchZero = Version.parse("2.1.1.0") + val old = Version.parse("1.1.0") + + assertThat(known).isGreaterThan(old) + assertThat(known).isLessThan(knownPlusPatch) + assertThat(known).isLessThan(knownPlusMinor) + assertThat(known).isGreaterThan(knownMinorOnly) + assertThat(knownPlusPatch).isLessThan(knownPlusPatchZero) + assertThat(known).isEquivalentAccordingToCompareTo(known) + } +}