From 7140e138f6c0bd72c6729c8373362e3caf71381d Mon Sep 17 00:00:00 2001 From: Timothy <6560631+TimoPtr@users.noreply.github.com> Date: Thu, 21 May 2026 10:29:46 +0200 Subject: [PATCH 1/7] Forbid usage of Build.Version.SDK_INT in favor of sdkVersion --- .../android/common/util/SdkVersionProvider.kt | 41 +++++++ .../io/homeassistant/lint/LintRegistry.kt | 2 + .../lint/sdkversion/SdkVersionDetector.kt | 72 +++++++++++ .../lint/sdkversion/SdkVersionDetectorTest.kt | 116 ++++++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt create mode 100644 lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt create mode 100644 lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt new file mode 100644 index 00000000000..bd11835f0fa --- /dev/null +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt @@ -0,0 +1,41 @@ +package io.homeassistant.companion.android.common.util + +import android.annotation.SuppressLint +import android.os.Build +import androidx.annotation.ChecksSdkIntAtLeast +import androidx.annotation.VisibleForTesting + +/** + * Reports whether the current Android SDK level is at least [api]. Tests can substitute a fake + * provider to simulate a SDK version. + * + * The [ChecksSdkIntAtLeast] annotation tells Android Lint that calls to [isAtLeast] are valid + * SDK version gates, so callers can reference newer-API symbols below the check without needing + * `@SuppressLint("NewApi")`. + */ +fun interface SdkVersionProvider { + @ChecksSdkIntAtLeast(parameter = 0) + fun isAtLeast(api: Int): Boolean +} + +/** + * Default [SdkVersionProvider] backed by the real device's [Build.VERSION.SDK_INT]. This is the + * single intentional raw read of `SDK_INT` in production code, so the `SdkVersionAccess` Lint + * rule is explicitly suppressed. + * + * The setter is [VisibleForTesting] only: tests that need to simulate a different SDK level + * can assign a fake here and restore the original in `@AfterEach`. + */ +@SuppressLint("SdkVersionAccess") +var sdkVersion: SdkVersionProvider = object : SdkVersionProvider { + @ChecksSdkIntAtLeast(parameter = 0) + override fun isAtLeast(api: Int): Boolean { + return Build.VERSION.SDK_INT >= api + } + + /** Returns the device's `SDK_INT` as a string, for use in diagnostic logging and registration payloads. */ + override fun toString(): String { + return Build.VERSION.SDK_INT.toString() + } +} + @VisibleForTesting set diff --git a/lint/src/main/kotlin/io/homeassistant/lint/LintRegistry.kt b/lint/src/main/kotlin/io/homeassistant/lint/LintRegistry.kt index d93e6c4b582..17cb5b1d444 100644 --- a/lint/src/main/kotlin/io/homeassistant/lint/LintRegistry.kt +++ b/lint/src/main/kotlin/io/homeassistant/lint/LintRegistry.kt @@ -6,6 +6,7 @@ import com.android.tools.lint.detector.api.CURRENT_API import com.android.tools.lint.detector.api.Issue import io.homeassistant.lint.annotation.NamedAnnotationDetector import io.homeassistant.lint.room.CoroutineDaoFunctionsIssue +import io.homeassistant.lint.sdkversion.SdkVersionDetector import io.homeassistant.lint.serialization.MissingSerializableAnnotationIssue import io.homeassistant.lint.webview.EvaluateJavascriptDetector @@ -16,6 +17,7 @@ class LintRegistry : IssueRegistry() { CoroutineDaoFunctionsIssue.ISSUE, NamedAnnotationDetector.ISSUE, EvaluateJavascriptDetector.ISSUE, + SdkVersionDetector.ISSUE, ) override val api: Int = CURRENT_API diff --git a/lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt b/lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt new file mode 100644 index 00000000000..03876c7c196 --- /dev/null +++ b/lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt @@ -0,0 +1,72 @@ +package io.homeassistant.lint.sdkversion + +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiField +import org.jetbrains.uast.UReferenceExpression + +private const val SDK_INT_FIELD_NAME = "SDK_INT" +private const val BUILD_VERSION_FQN = "android.os.Build.VERSION" + +object SdkVersionDetector { + + @JvmField + val ISSUE = Issue.create( + id = "SdkVersionAccess", + briefDescription = "Direct read of Build.VERSION.SDK_INT bypasses the sdkVersion provider", + explanation = """ + Production code should call `sdkVersion.isAtLeast(api)` instead of reading + `Build.VERSION.SDK_INT` directly for version gates. The provider has a + `@VisibleForTesting` setter so tests can simulate other SDK levels, and its + `@ChecksSdkIntAtLeast(parameter = 0)` annotation lets Android Lint recognise the + version gate without `@SuppressLint("NewApi")`. + + When you need the raw `SDK_INT` value as a string — typically for diagnostic + logging or registration payloads — use `sdkVersion.toString()` (or string + interpolation `"... ${"$"}sdkVersion ..."`) instead of `Build.VERSION.SDK_INT.toString()`. + + If a call site genuinely needs to read `Build.VERSION.SDK_INT` directly (typically + the single declaration of `sdkVersion` itself), suppress with + `@SuppressLint("SdkVersionAccess")` on the enclosing function, property, or class + and document why in code review. + """.trimIndent(), + category = Category.CORRECTNESS, + priority = 8, + severity = Severity.ERROR, + implementation = Implementation( + IssueDetector::class.java, + Scope.JAVA_FILE_SCOPE, + ), + ) + + class IssueDetector : + Detector(), + SourceCodeScanner { + + override fun getApplicableReferenceNames(): List = listOf(SDK_INT_FIELD_NAME) + + override fun visitReference(context: JavaContext, reference: UReferenceExpression, referenced: PsiElement) { + if (referenced !is PsiField) return + val containingClass = referenced.containingClass ?: return + if (containingClass.qualifiedName != BUILD_VERSION_FQN) return + + context.report( + ISSUE, + reference, + context.getLocation(reference), + "Read of `Build.VERSION.SDK_INT` is forbidden. Use `sdkVersion.isAtLeast(api)` " + + "for version gates, or `sdkVersion.toString()` / `\"... \$sdkVersion ...\"` " + + "when you need the raw value as a string. Suppress with " + + "`@SuppressLint(\"SdkVersionAccess\")` only if this site is one of the few " + + "legitimate raw accesses.", + ) + } + } +} diff --git a/lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt b/lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt new file mode 100644 index 00000000000..736228f93c0 --- /dev/null +++ b/lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt @@ -0,0 +1,116 @@ +package io.homeassistant.lint.sdkversion + +import com.android.tools.lint.checks.infrastructure.TestFiles.kotlin +import com.android.tools.lint.checks.infrastructure.TestLintTask.lint +import org.junit.Test + +class SdkVersionDetectorTest { + + private val buildVersionStub = kotlin( + """ + package android.os + + class Build { + class VERSION { + companion object { + @JvmField val SDK_INT: Int = 0 + } + } + } + """, + ).indented() + + @Test + fun `Given Build_VERSION_SDK_INT read without suppression then error is reported`() { + lint().issues(SdkVersionDetector.ISSUE) + .allowMissingSdk() + .files( + buildVersionStub, + kotlin( + """ + package com.example + + import android.os.Build + + fun checkSdk(): Boolean = Build.VERSION.SDK_INT >= 30 + """, + ).indented(), + ) + .run() + .expect( + """ + src/com/example/test.kt:5: Error: Read of Build.VERSION.SDK_INT is forbidden. Use sdkVersion.isAtLeast(api) for version gates, or sdkVersion.toString() / "... ${"$"}sdkVersion ..." when you need the raw value as a string. Suppress with @SuppressLint("SdkVersionAccess") only if this site is one of the few legitimate raw accesses. [SdkVersionAccess] + fun checkSdk(): Boolean = Build.VERSION.SDK_INT >= 30 + ~~~~~~~ + 1 error + """.trimIndent(), + ) + } + + @Test + fun `Given SDK_INT read suppressed on enclosing function then no error`() { + lint().issues(SdkVersionDetector.ISSUE) + .allowMissingSdk() + .files( + buildVersionStub, + kotlin( + """ + package com.example + + import android.annotation.SuppressLint + import android.os.Build + + @SuppressLint("SdkVersionAccess") + fun checkSdk(): Boolean = Build.VERSION.SDK_INT >= 30 + """, + ).indented(), + ) + .run() + .expectClean() + } + + @Test + fun `Given SDK_INT read suppressed on enclosing class then no error`() { + lint().issues(SdkVersionDetector.ISSUE) + .allowMissingSdk() + .files( + buildVersionStub, + kotlin( + """ + package com.example + + import android.annotation.SuppressLint + import android.os.Build + + @SuppressLint("SdkVersionAccess") + class Helper { + fun checkSdk(): Boolean = Build.VERSION.SDK_INT >= 30 + } + """, + ).indented(), + ) + .run() + .expectClean() + } + + @Test + fun `Given an unrelated SDK_INT constant on a different class then no error`() { + lint().issues(SdkVersionDetector.ISSUE) + .allowMissingSdk() + .files( + kotlin( + """ + package com.example + + object MyConstants { + const val SDK_INT: Int = 42 + } + + fun useUnrelatedConstant(): Int = MyConstants.SDK_INT + """, + ).indented(), + ) + .run() + .expectClean() + } +} From b57e89979d549b45d8cf0604d049dca4d9089d9c Mon Sep 17 00:00:00 2001 From: Timothy <6560631+TimoPtr@users.noreply.github.com> Date: Thu, 21 May 2026 10:51:52 +0200 Subject: [PATCH 2/7] Replace Build.Version.SDK_INT usage --- .../developer/DemoExoPlayerActivity.kt | 3 +- .../location/HighAccuracyLocationService.kt | 5 +-- .../android/matter/MatterManagerImpl.kt | 3 +- .../android/sensors/ActivitySensorManager.kt | 3 +- .../sensors/AndroidAutoSensorManager.kt | 5 +-- .../android/sensors/LocationSensorManager.kt | 18 +++++++---- .../android/thread/ThreadManagerImpl.kt | 3 +- .../android/HomeAssistantApplication.kt | 11 ++++--- .../android/assist/AssistActivity.kt | 5 +-- .../service/AssistRecognitionService.kt | 3 +- .../service/AssistVoiceInteractionService.kt | 7 ++-- .../companion/android/controls/HaControl.kt | 3 +- .../controls/HaControlsProviderService.kt | 7 ++-- .../haptic/HapticFeedbackPerformer.kt | 9 +++--- .../frontend/permissions/PermissionManager.kt | 32 ++++--------------- .../android/improv/ImprovRepositoryImpl.kt | 3 +- .../android/improv/ui/ImprovSheetView.kt | 3 +- .../android/launch/LaunchActivity.kt | 3 +- .../android/notifications/MessagingManager.kt | 21 ++++++------ .../serverdiscovery/HomeAssistantSearcher.kt | 3 +- .../serverdiscovery/ServerDiscoveryScreen.kt | 3 +- .../companion/android/qs/TileExtensions.kt | 9 +++--- .../android/qs/TilePreferenceActivity.kt | 3 +- .../android/sensors/CarSensorManager.kt | 3 +- .../android/sensors/GeocodeSensorManager.kt | 6 ++-- .../android/sensors/LastAppSensorManager.kt | 3 +- .../sensors/NotificationSensorManager.kt | 7 ++-- .../android/settings/SettingsFragment.kt | 21 ++++++------ .../android/settings/SettingsPresenterImpl.kt | 3 +- .../assist/DefaultAssistantManager.kt | 3 +- .../controls/ManageControlsViewModel.kt | 5 +-- .../controls/views/ManageControlsView.kt | 5 +-- .../settings/language/LanguagesManager.kt | 9 +++--- .../android/settings/log/LogFragment.kt | 5 +-- .../settings/qs/ManageTilesViewModel.kt | 5 +-- .../settings/qs/views/ManageTilesView.kt | 3 +- .../settings/sensor/SensorDetailFragment.kt | 5 +-- .../settings/sensor/SensorDetailViewModel.kt | 7 ++-- .../sensor/views/SensorUpdateFrequencyView.kt | 3 +- .../shortcuts/ManageShortcutsViewModel.kt | 7 ++-- .../android/settings/ssid/SsidFragment.kt | 11 ++++--- .../android/settings/ssid/views/SsidView.kt | 3 +- .../websocket/views/WebsocketSettingView.kt | 3 +- .../widgets/ManageWidgetsViewModel.kt | 3 +- .../android/themes/NightModeManager.kt | 3 +- .../android/util/ContextExtensions.kt | 3 +- .../android/util/DataUriDownloadManager.kt | 5 +-- .../util/compose/LocationPermissionState.kt | 9 +++--- .../android/util/compose/webview/HAWebView.kt | 3 +- .../android/util/vehicle/NativeMode.kt | 3 +- .../android/util/vehicle/SettingsAction.kt | 3 +- .../android/websocket/WebsocketManager.kt | 7 ++-- .../android/webview/WebViewActivity.kt | 11 ++++--- .../android/webview/WebViewContentScreen.kt | 3 +- .../button/ButtonWidgetConfigureActivity.kt | 3 +- .../camera/CameraWidgetConfigureActivity.kt | 3 +- .../entity/EntityWidgetConfigureActivity.kt | 3 +- ...iaPlayerControlsWidgetConfigureActivity.kt | 3 +- .../TemplateWidgetConfigureActivity.kt | 3 +- .../todo/TodoWidgetConfigureActivity.kt | 3 +- .../android/widgets/todo/TodoWidgetState.kt | 3 +- .../android/location/LocationProvider.kt | 4 +-- .../permissions/PermissionManagerTest.kt | 10 +++++- .../common/bluetooth/ble/MonitoringManager.kt | 3 +- .../compose/util/PainterResourceUtil.kt | 3 +- .../android/common/data/integration/Entity.kt | 3 +- .../common/data/network/WifiHelperImpl.kt | 3 +- .../NotificationDeleteReceiver.kt | 3 +- .../notifications/NotificationFunctions.kt | 7 ++-- .../common/sensors/AppSensorManagerBase.kt | 5 +-- .../common/sensors/AudioSensorManager.kt | 11 ++++--- .../common/sensors/BatterySensorManager.kt | 11 ++++--- .../common/sensors/BluetoothSensorManager.kt | 11 ++++--- .../common/sensors/MobileDataManager.kt | 7 ++-- .../common/sensors/NetworkSensorManager.kt | 28 ++++++++-------- .../common/sensors/PhoneStateSensorManager.kt | 11 ++++--- .../android/common/sensors/SensorManager.kt | 5 +-- .../common/sensors/SensorReceiverBase.kt | 3 +- .../common/sensors/SensorWorkerBase.kt | 5 +-- .../common/sensors/StepsSensorManager.kt | 3 +- .../common/util/DisabledLocationHandler.kt | 5 ++- .../android/common/util/ExoPlayerExt.kt | 2 +- .../util/NotificationManagerExtensions.kt | 2 +- .../android/database/migration/Utils.kt | 3 +- .../companion/android/di/DataModule.kt | 3 +- .../android/HomeAssistantApplication.kt | 9 +++--- .../companion/android/home/HomeActivity.kt | 3 +- .../companion/android/home/views/SensorUi.kt | 5 +-- .../sensors/BedtimeModeSensorManager.kt | 3 +- .../sensors/HealthServicesSensorManager.kt | 3 +- .../android/sensors/HeartRateSensorManager.kt | 3 +- .../companion/android/tiles/TileViews.kt | 3 +- 92 files changed, 305 insertions(+), 231 deletions(-) diff --git a/app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt b/app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt index ad66a03bedc..36918ddf333 100644 --- a/app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt +++ b/app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt @@ -32,6 +32,7 @@ import androidx.media3.common.Player import androidx.media3.datasource.DataSource import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.common.util.initializePlayer +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme import io.homeassistant.companion.android.util.compose.media.player.HAMediaPlayer import javax.inject.Inject @@ -98,7 +99,7 @@ private fun HAMediaPlayer( player = null } - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { // Initialize/release in onStart()/onStop() only because in a multi-window environment multiple // apps can be visible at the same time. The apps that are out-of-focus are paused, but video // playback should continue. diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt b/app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt index 4de3aef9d8c..67c5aa01778 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt @@ -22,6 +22,7 @@ import com.google.android.gms.location.Priority import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.CHANNEL_HIGH_ACCURACY import io.homeassistant.companion.android.common.util.FailFast +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.sensors.LocationSensorManager import io.homeassistant.companion.android.util.ForegroundServiceLauncher import kotlin.math.abs @@ -111,7 +112,7 @@ class HighAccuracyLocationService : Service() { } private fun createNotificationBuilder(context: Context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val channel = NotificationChannel( CHANNEL_HIGH_ACCURACY, @@ -153,7 +154,7 @@ class HighAccuracyLocationService : Service() { createNotificationBuilder(this) notification = notificationBuilder.build() - val type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) FOREGROUND_SERVICE_TYPE_LOCATION else 0 + val type = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) FOREGROUND_SERVICE_TYPE_LOCATION else 0 FailFast.failOnCatch { // Sometimes the service cannot be started as foreground due to the app being in a state where // this is not allowed. We haven't identified how to avoid starting the service in this state yet. diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt b/app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt index 217dd675084..80a556473f3 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt @@ -10,6 +10,7 @@ import com.google.android.gms.home.matter.commissioning.CommissioningRequest import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.MatterCommissionResponse import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject import kotlinx.coroutines.CancellationException import timber.log.Timber @@ -19,7 +20,7 @@ class MatterManagerImpl @Inject constructor( private val packageManager: PackageManager, ) : MatterManager { - override fun appSupportsCommissioning(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 && + override fun appSupportsCommissioning(): Boolean = sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) && !packageManager.isAutomotive() override suspend fun coreSupportsCommissioning(serverId: Int): Boolean { diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt index 6de1b1aef8d..f130e850ef4 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt @@ -18,6 +18,7 @@ import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.sensors.SensorReceiverBase import io.homeassistant.companion.android.common.util.STATE_UNKNOWN import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import java.util.concurrent.TimeUnit import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -211,7 +212,7 @@ class ActivitySensorManager : } override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf( Manifest.permission.ACTIVITY_RECOGNITION, ) diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt index af1164bd516..cd70a267f86 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt @@ -6,6 +6,7 @@ import androidx.car.app.connection.CarConnection import androidx.lifecycle.Observer import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager +import io.homeassistant.companion.android.common.util.sdkVersion import kotlinx.coroutines.launch import timber.log.Timber @@ -29,7 +30,7 @@ class AndroidAutoSensorManager : get() = commonR.string.sensor_name_android_auto override suspend fun getAvailableSensors(context: Context): List { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { listOf(androidAutoConnected) } else { emptyList() @@ -37,7 +38,7 @@ class AndroidAutoSensorManager : } override fun hasSensor(context: Context): Boolean { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + return sdkVersion.isAtLeast(Build.VERSION_CODES.O) } override fun requiredPermissions(context: Context, sensorId: String): Array { diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt index 6e5c95f2b81..bd4759f68b5 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt @@ -36,6 +36,7 @@ import io.homeassistant.companion.android.common.notifications.DeviceCommandData import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.sensors.SensorReceiverBase import io.homeassistant.companion.android.common.util.DisabledLocationHandler +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.DatabaseEntryPoint import io.homeassistant.companion.android.database.location.LocationHistoryDao import io.homeassistant.companion.android.database.location.LocationHistoryItem @@ -861,9 +862,7 @@ class LocationSensorManager : "provider" to geofencingEvent.triggeringLocation!!.provider, "time" to geofencingEvent.triggeringLocation!!.time, "vertical_accuracy" to - if (Build.VERSION.SDK_INT >= - 26 - ) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { geofencingEvent.triggeringLocation!!.verticalAccuracyMeters.toInt() } else { 0 @@ -976,7 +975,14 @@ class LocationSensorManager : speed = location.speed.toInt(), altitude = location.altitude.toInt(), course = location.bearing.toInt(), - verticalAccuracy = if (Build.VERSION.SDK_INT >= 26) location.verticalAccuracyMeters.toInt() else 0, + verticalAccuracy = if (sdkVersion.isAtLeast( + Build.VERSION_CODES.O, + ) + ) { + location.verticalAccuracyMeters.toInt() + } else { + 0 + }, ) updateLocationString = updateLocation.gps.toString() } @@ -1362,7 +1368,7 @@ class LocationSensorManager : override fun requiredPermissions(context: Context, sensorId: String): Array { return when { - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> { + (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, @@ -1372,7 +1378,7 @@ class LocationSensorManager : ) } - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) -> { + (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) -> { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt b/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt index 6c2c5e70ce0..8954108f052 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt @@ -16,6 +16,7 @@ import io.homeassistant.companion.android.common.data.HomeAssistantVersion import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.ThreadDatasetResponse import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException @@ -33,7 +34,7 @@ class ThreadManagerImpl @Inject constructor( private const val BORDER_AGENT_ID = "0000000000000001" } - override fun appSupportsThread(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 && + override fun appSupportsThread(): Boolean = sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) && !packageManager.isAutomotive() override suspend fun coreSupportsThread(serverId: Int): Boolean { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt b/app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt index c19123d38d4..f5c5145ac40 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt @@ -26,6 +26,7 @@ import io.homeassistant.companion.android.common.sensors.LastUpdateManager import io.homeassistant.companion.android.common.util.HAStrictMode import io.homeassistant.companion.android.common.util.configureComposeDiagnosticStackTrace import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.SensorDao import io.homeassistant.companion.android.database.settings.SensorUpdateFrequencySetting import io.homeassistant.companion.android.database.settings.SettingsDao @@ -86,7 +87,7 @@ open class HomeAssistantApplication : Timber.plant(Timber.DebugTree()) super.onCreate() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + if (sdkVersion.isAtLeast(Build.VERSION_CODES.S) && BuildConfig.DEBUG && !BuildConfig.NO_STRICT_MODE ) { @@ -96,7 +97,7 @@ open class HomeAssistantApplication : ) } - Timber.i("Running ${BuildConfig.VERSION_NAME} on SDK ${Build.VERSION.SDK_INT}") + Timber.i("Running ${BuildConfig.VERSION_NAME} on SDK $sdkVersion") registerActivityLifecycleCallbacks(LifecycleHandler) @@ -239,7 +240,7 @@ open class HomeAssistantApplication : ) // Listen for microphone mute changes - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { ContextCompat.registerReceiver( this, sensorReceiver, @@ -249,7 +250,7 @@ open class HomeAssistantApplication : } // Listen for speakerphone state changes - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { ContextCompat.registerReceiver( this, sensorReceiver, @@ -304,7 +305,7 @@ open class HomeAssistantApplication : } // Register for changes to the managed profile availability - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { ContextCompat.registerReceiver( this, sensorReceiver, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt index 3778168ad1d..be7fa30bcef 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt @@ -21,6 +21,7 @@ import io.homeassistant.companion.android.assist.service.AssistVoiceInteractionS import io.homeassistant.companion.android.assist.ui.AssistSheetView import io.homeassistant.companion.android.common.assist.AssistViewModelBase import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.launch.LaunchActivity import io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme import io.homeassistant.companion.android.webview.WebViewActivity @@ -192,7 +193,7 @@ class AssistActivity : BaseActivity() { contextIsLocked = locked if (locked) { window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) { + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1)) { @Suppress("DEPRECATION") window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) } else { @@ -200,7 +201,7 @@ class AssistActivity : BaseActivity() { setTurnScreenOn(true) } } else { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) { + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1)) { @Suppress("DEPRECATION") window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) } else { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt b/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt index 9a265638ce8..e90815f1da6 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt @@ -4,6 +4,7 @@ import android.content.Intent import android.os.Build import android.speech.RecognitionService import android.speech.SpeechRecognizer +import io.homeassistant.companion.android.common.util.sdkVersion import timber.log.Timber /** @@ -21,7 +22,7 @@ class AssistRecognitionService : RecognitionService() { } override fun onCheckRecognitionSupport(recognizerIntent: Intent, supportCallback: SupportCallback) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { supportCallback.onError(SpeechRecognizer.ERROR_CLIENT) } } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt b/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt index 0601410d784..a158c87b9c9 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt @@ -26,6 +26,7 @@ import io.homeassistant.companion.android.assist.wakeword.WakeWordListener import io.homeassistant.companion.android.assist.wakeword.WakeWordListenerFactory import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.CHANNEL_ASSIST_LISTENING +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.settings.assist.AssistConfigManager import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -222,7 +223,7 @@ class AssistVoiceInteractionService : VoiceInteractionService() { PackageManager.PERMISSION_GRANTED private fun startForegroundWithNotification(model: MicroWakeWordModelConfig) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { startForeground( NOTIFICATION_ID, createNotification(model), @@ -234,7 +235,7 @@ class AssistVoiceInteractionService : VoiceInteractionService() { } private fun stopForegroundCompat() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { stopForeground(STOP_FOREGROUND_REMOVE) } else { @Suppress("DEPRECATION") @@ -281,7 +282,7 @@ class AssistVoiceInteractionService : VoiceInteractionService() { } private fun createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val channel = NotificationChannel( CHANNEL_ASSIST_LISTENING, getString(commonR.string.assist_listening_channel), diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt b/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt index cdd2ec7a2c6..12d02a2e470 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt @@ -21,6 +21,7 @@ import io.homeassistant.companion.android.common.data.integration.IntegrationRep import io.homeassistant.companion.android.common.data.integration.friendlyState import io.homeassistant.companion.android.common.data.integration.getIcon import io.homeassistant.companion.android.common.data.integration.isActive +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.webview.WebViewActivity @RequiresApi(Build.VERSION_CODES.R) @@ -57,7 +58,7 @@ interface HaControl { } control.setStatus(Control.STATUS_OK) control.setStatusText(entity.friendlyState(context)) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { control.setAuthRequired(info.authRequired) } if (entity.attributes["icon"]?.toString()?.startsWith("mdi:") == true && diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt b/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt index 8045f1409d2..943559e2ca9 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt @@ -18,6 +18,7 @@ import io.homeassistant.companion.android.common.data.servers.firstUrlOrNull import io.homeassistant.companion.android.common.data.websocket.impl.entities.AreaRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.DeviceRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.util.RegistriesDataHandler import java.time.LocalDateTime import java.util.concurrent.Flow @@ -72,7 +73,7 @@ class HaControlsProviderService : ControlsProviderService() { .map { it.key } .filter { domainToMinimumApi[it] == null || - Build.VERSION.SDK_INT >= domainToMinimumApi[it]!! + sdkVersion.isAtLeast(domainToMinimumApi[it]!!) } } @@ -149,7 +150,7 @@ class HaControlsProviderService : ControlsProviderService() { allEntities .filter { domainToMinimumApi[it.second.domain] == null || - Build.VERSION.SDK_INT >= domainToMinimumApi[it.second.domain]!! + sdkVersion.isAtLeast(domainToMinimumApi[it.second.domain]!!) } .mapNotNull { (serverId, entity) -> try { @@ -555,7 +556,7 @@ class HaControlsProviderService : ControlsProviderService() { ) private suspend fun entityRequiresAuth(entityId: String, serverId: Int): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { val setting = prefsRepository.getControlsAuthRequired() if (setting == ControlsAuthRequiredSetting.SELECTION) { val includeList = prefsRepository.getControlsAuthEntities() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt b/app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt index 91fd1d0dcff..0203149b231 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt @@ -6,6 +6,7 @@ import android.os.Vibrator import android.view.HapticFeedbackConstants import android.view.View import androidx.core.content.getSystemService +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.frontend.externalbus.incoming.HapticType import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -48,7 +49,7 @@ object HapticFeedbackPerformer { } private fun performSuccess(view: View) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { view.performHapticFeedback(HapticFeedbackConstants.CONFIRM) } else { vibrate(view, duration = SUCCESS_FALLBACK_DURATION) @@ -56,7 +57,7 @@ object HapticFeedbackPerformer { } private fun performWarning(view: View) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { view.context.getSystemService()?.vibrate( VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK), ) @@ -66,7 +67,7 @@ object HapticFeedbackPerformer { } private fun performFailure(view: View) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { view.performHapticFeedback(HapticFeedbackConstants.REJECT) } else { vibrate(view, duration = FAILURE_FALLBACK_DURATION) @@ -74,7 +75,7 @@ object HapticFeedbackPerformer { } private fun performSelection(view: View) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { view.performHapticFeedback(HapticFeedbackConstants.GESTURE_START) } else { vibrate(view, duration = SELECTION_FALLBACK_DURATION) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt index 48bc4b8e54d..fc401485094 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt @@ -1,14 +1,13 @@ package io.homeassistant.companion.android.frontend.permissions import android.Manifest -import android.annotation.SuppressLint import android.os.Build import android.webkit.PermissionRequest as WebViewPermissionRequest -import androidx.annotation.VisibleForTesting import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.NotificationStatusProvider import io.homeassistant.companion.android.common.util.PermissionChecker import io.homeassistant.companion.android.common.util.SingleSlotQueue +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.settings.SensorUpdateFrequencySetting import io.homeassistant.companion.android.database.settings.Setting import io.homeassistant.companion.android.database.settings.SettingsDao @@ -39,32 +38,15 @@ private data class WebViewPermissionStatus( * Concurrent triggers are waiting in FIFO order: a second method call suspends until the * current request is resolved. */ -internal class PermissionManager @VisibleForTesting constructor( +internal class PermissionManager @Inject constructor( private val serverManager: ServerManager, private val settingsDao: SettingsDao, @FcmSupport private val fcmSupport: Boolean, private val notificationStatusProvider: NotificationStatusProvider, private val permissionChecker: PermissionChecker, // Need for testing to avoid the need of Robolectric - private val sdkInt: Int, ) { - @Inject - constructor( - serverManager: ServerManager, - settingsDao: SettingsDao, - @FcmSupport fcmSupport: Boolean, - notificationStatusProvider: NotificationStatusProvider, - permissionChecker: PermissionChecker, - ) : this( - serverManager = serverManager, - settingsDao = settingsDao, - fcmSupport = fcmSupport, - notificationStatusProvider = notificationStatusProvider, - permissionChecker = permissionChecker, - sdkInt = Build.VERSION.SDK_INT, - ) - private val queue = SingleSlotQueue() /** The current pending permission request that needs user approval, or null if none. */ @@ -86,9 +68,8 @@ internal class PermissionManager @VisibleForTesting constructor( * * @param serverId The server to check notification preferences for */ - @SuppressLint("NewApi") suspend fun checkNotificationPermission(serverId: Int) { - if (sdkInt < Build.VERSION_CODES.TIRAMISU) return + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) return if (!shouldAskNotificationPermission(serverId)) return val granted: Boolean? = queue.awaitResult { resolve -> @@ -115,9 +96,8 @@ internal class PermissionManager @VisibleForTesting constructor( * @return `true` if local network access is available (granted or not required); `false` if the * user declined the permission */ - @SuppressLint("NewApi") suspend fun checkLocalNetworkPermission(): Boolean { - if (sdkInt < Build.VERSION_CODES.CINNAMON_BUN) return true + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return true if (permissionChecker.hasPermission(Manifest.permission.ACCESS_LOCAL_NETWORK)) return true Timber.d("Local network permission required, awaiting user response") @@ -138,8 +118,8 @@ internal class PermissionManager @VisibleForTesting constructor( * the user declined the permission */ suspend fun checkStoragePermissionForDownload(): Boolean { - if (sdkInt >= Build.VERSION_CODES.Q) return true - if (permissionChecker.hasPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) return true + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) return true + if (permissionChecker.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) return true Timber.d("Storage permission required for download, awaiting user response") return queue.awaitResult { onResult -> diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt b/app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt index dea4d277264..42094a0dc46 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt @@ -10,6 +10,7 @@ import com.wifi.improv.ErrorState import com.wifi.improv.ImprovDevice import com.wifi.improv.ImprovManager import com.wifi.improv.ImprovManagerCallback +import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -39,7 +40,7 @@ class ImprovRepositoryImpl @Inject constructor() : override fun getRequiredPermissions(): Array { var required = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { required += Manifest.permission.BLUETOOTH_SCAN required += Manifest.permission.BLUETOOTH_CONNECT } else { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt index 73d3af047aa..7cc5d1f21fb 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt @@ -50,6 +50,7 @@ import com.wifi.improv.DeviceState import com.wifi.improv.ErrorState import com.wifi.improv.ImprovDevice import io.homeassistant.companion.android.common.R as commonR +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.util.compose.ModalBottomSheet @Composable @@ -94,7 +95,7 @@ fun ImprovSheetView( ImprovWifiInput( activeSsid = if (screenState.activeSsid?.isNotBlank() == true && ( - Build.VERSION.SDK_INT < Build.VERSION_CODES.R || + !sdkVersion.isAtLeast(Build.VERSION_CODES.R) || screenState.activeSsid !== WifiManager.UNKNOWN_SSID ) ) { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt index 5b6d3194b6d..e8b73b36ffe 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt @@ -40,6 +40,7 @@ import io.homeassistant.companion.android.authenticator.Authenticator import io.homeassistant.companion.android.authenticator.Authenticator.Companion.AuthenticationResult import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.compose.theme.HATheme +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.launch.applock.HazeLockOverlay import io.homeassistant.companion.android.sensors.SensorReceiver import io.homeassistant.companion.android.sensors.SensorWorker @@ -246,7 +247,7 @@ class LaunchActivity : AppCompatActivity() { if (WIPFeature.USE_FRONTEND_V2) { viewModel.onAppPaused() - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O)) return if (!packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) return val readiness = viewModel.pipReadiness.value ?: return val params = PictureInPictureParams.Builder() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt index c6455de9911..92f3f0960e4 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt @@ -70,6 +70,7 @@ import io.homeassistant.companion.android.common.util.cancelGroupIfNeeded import io.homeassistant.companion.android.common.util.getActiveNotification import io.homeassistant.companion.android.common.util.isAutomotive import io.homeassistant.companion.android.common.util.kotlinJsonMapper +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.common.util.toJsonObject import io.homeassistant.companion.android.common.util.tts.TextToSpeechClient import io.homeassistant.companion.android.common.util.tts.TextToSpeechData @@ -420,7 +421,7 @@ class MessagingManager @Inject constructor( if ( !jsonData[NotificationData.COMMAND].isNullOrEmpty() && jsonData[NotificationData.COMMAND] in DeviceCommandData.ENABLE_COMMANDS && - Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU + !sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) ) { handleDeviceCommands(jsonData) } else { @@ -636,7 +637,7 @@ class MessagingManager @Inject constructor( val channelID: String = createChannelID(channelName) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && channelID != NotificationChannel.DEFAULT_CHANNEL_ID) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O) && channelID != NotificationChannel.DEFAULT_CHANNEL_ID) { notificationManagerCompat.deleteNotificationChannel(channelID) } } @@ -729,7 +730,7 @@ class MessagingManager @Inject constructor( COMMAND_BLUETOOTH -> { val bluetoothAdapter = context.getSystemService()?.adapter - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { when (PackageManager.PERMISSION_GRANTED) { ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) -> { Timber.d("We have proper bluetooth permissions proceeding with command") @@ -1021,7 +1022,7 @@ class MessagingManager @Inject constructor( group = NotificationData.GROUP_PREFIX + group groupId = group.hashCode() } else { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { val notification = notificationManagerCompat.getActiveNotification(tag, messageId) if (notification != null && notification.isGroup) { previousGroup = NotificationData.GROUP_PREFIX + notification.tag @@ -1078,7 +1079,7 @@ class MessagingManager @Inject constructor( val useCarNotification = handleCarUiVisible(context, notificationBuilder, data) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { handleLegacyPriority(notificationBuilder, data) handleLegacyLedColor(notificationBuilder, data) handleLegacyVibrationPattern(notificationBuilder, data) @@ -1124,7 +1125,7 @@ class MessagingManager @Inject constructor( builder.setWhen(notificationWhen) builder.setUsesChronometer(usesChronometer) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { val countdown = notificationWhen > System.currentTimeMillis() // Without this builder.setChronometerCountDown throws a null reference exception builder.addExtras(Bundle()) @@ -1151,7 +1152,7 @@ class MessagingManager @Inject constructor( } private fun handleLive(builder: NotificationCompat.Builder, data: Map) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.BAKLAVA)) { val liveUpdate = data[LIVE_UPDATE]?.toBoolean() ?: false val criticalText = data[CRITICAL_TEXT] @@ -1171,7 +1172,7 @@ class MessagingManager @Inject constructor( builder: NotificationCompat.Builder, data: Map, ): Boolean { - if (data[CAR_UI]?.toBoolean() == true && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (data[CAR_UI]?.toBoolean() == true && sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val carExtender = CarAppExtender.Builder() if (context.isAutomotive() || BuildConfig.FLAVOR == "full") { val carIntent = Intent(Intent.ACTION_VIEW).apply { @@ -1341,7 +1342,7 @@ class MessagingManager @Inject constructor( .setLargeIcon(bitmap) .setStyle( NotificationCompat.BigPictureStyle().also { style -> - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { saveTempAnimatedImage( serverId, url, @@ -1740,7 +1741,7 @@ class MessagingManager @Inject constructor( } private fun handleReplyHistory(builder: NotificationCompat.Builder, data: Map) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { val replies = data.entries .filter { it.key.startsWith(SOURCE_REPLY_HISTORY) } .sortedBy { it.key.substringAfter(SOURCE_REPLY_HISTORY).toInt() } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt b/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt index c8dc1bb203e..15da55ee5a6 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt @@ -7,6 +7,7 @@ import android.os.Build import androidx.annotation.VisibleForTesting import io.homeassistant.companion.android.common.data.HomeAssistantVersion import io.homeassistant.companion.android.common.util.FailFast +import io.homeassistant.companion.android.common.util.sdkVersion import java.net.MalformedURLException import java.net.URL import java.util.concurrent.atomic.AtomicBoolean @@ -157,7 +158,7 @@ internal class HomeAssistantSearcherImpl @Inject constructor( nsdManager.resolveService(serviceInfo, listener) awaitClose { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { try { nsdManager.stopServiceResolution(listener) } catch (e: IllegalArgumentException) { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt b/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt index 75ce3ba5ff2..eb658a0166f 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt @@ -90,6 +90,7 @@ import io.homeassistant.companion.android.common.compose.theme.HAThemeForPreview import io.homeassistant.companion.android.common.compose.theme.LocalHAColorScheme import io.homeassistant.companion.android.common.compose.theme.MaxButtonWidth import io.homeassistant.companion.android.common.data.HomeAssistantVersion +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.util.compose.HAPreviews import java.net.URL import kotlinx.coroutines.launch @@ -143,7 +144,7 @@ internal fun ServerDiscoveryScreen( @OptIn(ExperimentalPermissionsApi::class) @Composable private fun rememberLocalNetworkPermissionGranted(onDenied: () -> Unit): Boolean { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.CINNAMON_BUN) return true + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return true val permissionState = rememberPermissionState(Manifest.permission.ACCESS_LOCAL_NETWORK) { granted -> if (!granted) onDenied() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt b/app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt index eb4e47ad2d6..f5eddfb6f7c 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt @@ -30,6 +30,7 @@ import io.homeassistant.companion.android.common.data.integration.getIcon import io.homeassistant.companion.android.common.data.integration.isActive import io.homeassistant.companion.android.common.data.integration.onEntityPressedWithoutState import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.qs.TileDao import io.homeassistant.companion.android.database.qs.TileEntity import io.homeassistant.companion.android.database.qs.getHighestInUse @@ -146,7 +147,7 @@ abstract class TileExtensions : TileService() { try { return if (tileData != null && tileData.isSetup) { tile.label = tileData.label - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { tile.subtitle = tileData.subtitle } val state: Entity? = @@ -193,7 +194,7 @@ abstract class TileExtensions : TileService() { } else { Tile.STATE_UNAVAILABLE } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { tile.subtitle = getString(commonR.string.tile_not_setup) } tile.updateTile() @@ -212,7 +213,7 @@ abstract class TileExtensions : TileService() { val vm = getSystemService() if (!isUnlock) { if (tileData?.shouldVibrate == true) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { vm?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) } else { @Suppress("DEPRECATION") @@ -281,7 +282,7 @@ abstract class TileExtensions : TileService() { if (e != null) Timber.e(e, "Unable to call service for tile ID: ${tileData?.id}") if (tileData != null && tileData.shouldVibrate) { val vm = getSystemService() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { vm?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK)) } else { @Suppress("DEPRECATION") diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt index c2a552e09bf..ad474838a70 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt @@ -9,6 +9,7 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.BaseActivity import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.qs.TileDao import io.homeassistant.companion.android.database.qs.isSetup import io.homeassistant.companion.android.launch.LaunchActivity @@ -34,7 +35,7 @@ class TilePreferenceActivity : BaseActivity() { super.onCreate(savedInstanceState) var tileId = "-1" - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { intent.extras?.let { extras -> BundleCompat.getParcelable( extras, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt index 775c63734bb..b019e55953b 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt @@ -18,6 +18,7 @@ import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.vehicle.HaCarAppService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -219,7 +220,7 @@ class CarSensorManager : private lateinit var latestContext: Context @SuppressLint("ObsoleteSdkInt") // Needed for app module (minSdk 21) but obsolete for automotive (minSdk 29) - private val areCarSensorApisAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + private val areCarSensorApisAvailable = sdkVersion.isAtLeast(Build.VERSION_CODES.O) private val isAutomotive get() = latestContext.isAutomotive() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt index c20225cb33b..e067630684c 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt @@ -6,12 +6,12 @@ import android.location.Address import android.location.Geocoder import android.location.Location import android.os.Build -import android.os.Build.VERSION.SDK_INT import androidx.annotation.VisibleForTesting import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNKNOWN import io.homeassistant.companion.android.common.util.instant +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType import io.homeassistant.companion.android.location.HighAccuracyLocationService @@ -73,7 +73,7 @@ class GeocodeSensorManager : SensorManager { } override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (SDK_INT >= Build.VERSION_CODES.Q) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, @@ -168,7 +168,7 @@ class GeocodeSensorManager : SensorManager { longitude: Double, maxResults: Int, ): List
{ - return if (SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { suspendCoroutine { cont -> getFromLocation( latitude, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt index 05372aa50a0..9f085283d40 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt @@ -10,6 +10,7 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNKNOWN import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import timber.log.Timber class LastAppSensorManager : SensorManager { @@ -62,7 +63,7 @@ class LastAppSensorManager : SensorManager { try { val pm = context.packageManager - val appInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + val appInfo = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { pm.getApplicationInfo( lastApp, PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong()), diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt index 27e939ba57b..11bee0e03c3 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt @@ -19,6 +19,7 @@ import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.SensorSettingType import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -160,7 +161,7 @@ class NotificationSensorManager : put("group_id", sbn.notification.group) put("category", sbn.notification.category) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { put("channel_id", sbn.notification.channelId) } } @@ -223,7 +224,7 @@ class NotificationSensorManager : put("group_id", sbn.notification.group) put("category", sbn.notification.category) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { put("channel_id", sbn.notification.channelId) } } @@ -269,7 +270,7 @@ class NotificationSensorManager : put("${item.packageName}_${item.id}_group_id", item.notification.group) put("${item.packageName}_${item.id}_category", item.notification.category) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { put("${item.packageName}_${item.id}_channel_id", item.notification.channelId) } } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt index 55e580b4d75..223679464ed 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt @@ -31,6 +31,7 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.isAutomotive import io.homeassistant.companion.android.common.util.isIgnoringBatteryOptimizations import io.homeassistant.companion.android.common.util.maybeAskForIgnoringBatteryOptimizations +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.launch.intentLaunchOnboarding import io.homeassistant.companion.android.nfc.NfcSetupActivity @@ -208,7 +209,7 @@ class SettingsFragment( } if (!QuestUtil.isQuest) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N_MR1)) { findPreference("shortcuts")?.let { it.isVisible = true } @@ -221,7 +222,7 @@ class SettingsFragment( } } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { findPreference("quick_settings")?.let { it.isVisible = true } @@ -234,7 +235,7 @@ class SettingsFragment( } } - if (!isAutomotive && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (!isAutomotive && sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { findPreference("device_controls")?.let { it.isVisible = true } @@ -254,7 +255,7 @@ class SettingsFragment( updateNotificationChannelPrefs() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { findPreference("notification_permission")?.let { it.setOnPreferenceClickListener { openNotificationSettings() @@ -292,7 +293,7 @@ class SettingsFragment( if (rateLimits != null) { var formattedDate = rateLimits.resetsAt - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { try { val utcDateTime = Instant.parse(rateLimits.resetsAt) formattedDate = @@ -400,7 +401,7 @@ class SettingsFragment( findPreference("android_auto")?.let { it.isVisible = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + sdkVersion.isAtLeast(Build.VERSION_CODES.O) && (BuildConfig.FLAVOR == "full" || isAutomotive) if (isAutomotive) { it.title = getString(commonR.string.android_automotive) @@ -433,7 +434,7 @@ class SettingsFragment( } private fun removeSystemFromThemesIfNeeded() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { val pref = findPreference("themes") if (pref != null) { val systemIndex = pref.findIndexOfValue("system") @@ -529,7 +530,7 @@ class SettingsFragment( private fun updateNotificationChannelPrefs() { val notificationsEnabled = - Build.VERSION.SDK_INT < Build.VERSION_CODES.O || + !sdkVersion.isAtLeast(Build.VERSION_CODES.O) || NotificationManagerCompat.from(requireContext()).areNotificationsEnabled() findPreference("notification_permission")?.let { @@ -539,7 +540,7 @@ class SettingsFragment( val uiManager = requireContext().getSystemService() it.isVisible = notificationsEnabled && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + sdkVersion.isAtLeast(Build.VERSION_CODES.O) && uiManager?.currentModeType != Configuration.UI_MODE_TYPE_TELEVISION } } @@ -561,7 +562,7 @@ class SettingsFragment( } private fun openNotificationSettings() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { requestNotificationPermissionResult.launch( Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt index c2347fac559..11214159fc3 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt @@ -14,6 +14,7 @@ import io.homeassistant.companion.android.common.data.prefs.NightModeTheme import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.data.prefs.ScreenOrientation import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.database.settings.SettingsDao import io.homeassistant.companion.android.settings.assist.DefaultAssistantManager @@ -199,7 +200,7 @@ class SettingsPresenterImpl @Inject constructor( } // Notifications - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O) && !NotificationManagerCompat.from(context).areNotificationsEnabled() ) { suggestions += SettingsHomeSuggestion( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt index bf9c7c4208f..72840aee3c1 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt @@ -12,6 +12,7 @@ import io.homeassistant.companion.android.BuildConfig import io.homeassistant.companion.android.assist.service.AssistVoiceInteractionService import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject /** @@ -60,7 +61,7 @@ class DefaultAssistantManagerImpl @Inject constructor( // Not supported on automotive if (context.isAutomotive()) return false - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { val roleManager = context.getSystemService(RoleManager::class.java) roleManager?.isRoleAvailable(RoleManager.ROLE_ASSISTANT) == true && !roleManager.isRoleHeld(RoleManager.ROLE_ASSISTANT) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt index eb57c8e4ab0..5c335672786 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt @@ -18,6 +18,7 @@ import io.homeassistant.companion.android.common.data.integration.ControlsAuthRe import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.controls.HaControlsPanelActivity import io.homeassistant.companion.android.controls.HaControlsProviderService import io.homeassistant.companion.android.database.server.Server @@ -63,7 +64,7 @@ class ManageControlsViewModel @Inject constructor( init { viewModelScope.launch { servers = serverManager.servers() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { panelEnabled = application.packageManager.getComponentEnabledSetting( ComponentName(application, HaControlsPanelActivity::class.java), @@ -167,7 +168,7 @@ class ManageControlsViewModel @Inject constructor( } fun enablePanelForControls(enabled: Boolean) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) return + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) return application.packageManager.setComponentEnabledSetting( ComponentName(application, HaControlsPanelActivity::class.java), diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt index 835059a960e..a6a8993ef3d 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt @@ -58,6 +58,7 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.integration.ControlsAuthRequiredSetting import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.integration.friendlyName +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.util.compose.HaAlertWarning import io.homeassistant.companion.android.util.compose.ServerExposedDropdownMenu @@ -93,7 +94,7 @@ fun ManageControlsView( modifier = modifier, contentPadding = PaddingValues(vertical = 16.dp) + safeBottomPaddingValues(applyHorizontal = false), ) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { item { Text( text = stringResource(commonR.string.controls_setting_panel), @@ -128,7 +129,7 @@ fun ManageControlsView( } } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE || !panelEnabled) { + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) || !panelEnabled) { if (serversList.size > 1) { item { Row( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt index 6d5e77ffd85..6554fe34526 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt @@ -6,6 +6,7 @@ import androidx.appcompat.app.AppCompatDelegate import androidx.core.os.LocaleListCompat import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.prefs.PrefsRepository +import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -20,7 +21,7 @@ class LanguagesManager @Inject constructor(private var prefs: PrefsRepository) { suspend fun getCurrentLang(): String { val lang = prefs.getCurrentLang() - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { migrateLangSetting() AppCompatDelegate.getApplicationLocales().toLanguageTags().ifEmpty { DEF_LOCALE } } else { @@ -39,7 +40,7 @@ class LanguagesManager @Inject constructor(private var prefs: PrefsRepository) { withContext(Dispatchers.IO) { if (!lang.isNullOrEmpty()) { val currentLang = getCurrentLang() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { val languages = if (lang == DEF_LOCALE) { LocaleListCompat.getEmptyLocaleList() @@ -58,7 +59,7 @@ class LanguagesManager @Inject constructor(private var prefs: PrefsRepository) { suspend fun applyCurrentLang() { migrateLangSetting() - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) { + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { val lang = getCurrentLang() val languages = if (lang == DEF_LOCALE) { @@ -71,7 +72,7 @@ class LanguagesManager @Inject constructor(private var prefs: PrefsRepository) { } private suspend fun migrateLangSetting() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) return val lang = prefs.getCurrentLang() if (lang == SYSTEM_MANAGES_LOCALE) return diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt index ae8d8c32407..309d3df3e2a 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt @@ -30,6 +30,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.R import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.prefs.PrefsRepository +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.settings.addHelpMenuProvider import io.homeassistant.companion.android.util.LogcatReader import io.homeassistant.companion.android.util.applyBottomSafeDrawingInsets @@ -200,7 +201,7 @@ class LogFragment : Fragment() { // Also no issue template will be used val excludedComponents = getExcludedComponentsForPackageName(sendIntent, arrayOf("com.github.android")) - if (excludedComponents.size > 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (excludedComponents.size > 0 && sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponents.toTypedArray()) } } @@ -237,7 +238,7 @@ class LogFragment : Fragment() { packageNames: Array, ): ArrayList { val excludedComponents = ArrayList() - val resInfos = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + val resInfos = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { requireContext().packageManager.queryIntentActivities(sendIntent, PackageManager.ResolveInfoFlags.of(0)) } else { @Suppress("DEPRECATION") diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt index 2714ca49931..cb0e5616b8e 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt @@ -26,6 +26,7 @@ import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.AreaRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.DeviceRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.qs.TileDao import io.homeassistant.companion.android.database.qs.TileEntity import io.homeassistant.companion.android.database.qs.getHighestInUse @@ -228,7 +229,7 @@ class ManageTilesViewModel @Inject constructor( selectedShouldVibrate = it?.shouldVibrate ?: false tileAuthRequired = it?.authRequired ?: false submitButtonLabel = - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2 || it?.added == true) { + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) || it?.added == true) { commonR.string.tile_save } else { commonR.string.tile_add @@ -296,7 +297,7 @@ class ManageTilesViewModel @Inject constructor( val highestInUse = tileDao.getHighestInUse()?.numberedId ?: 0 updateActiveTileServices(highestInUse, app) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && !selectedTileAdded) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && !selectedTileAdded) { val statusBarManager = app.getSystemService() val service = idToTileService[selectedTile.id] ?: Tile1Service::class.java val icon = selectedIcon?.let { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt index a02e54bf8f2..6c92ae38ca4 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.compose.theme.HATheme +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.settings.qs.ManageTilesViewModel import io.homeassistant.companion.android.util.compose.ServerExposedDropdownMenu import io.homeassistant.companion.android.util.compose.entity.EntityPicker @@ -122,7 +123,7 @@ fun ManageTilesView( .fillMaxWidth(), ) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { TextField( value = viewModel.tileSubtitle.orEmpty(), onValueChange = { viewModel.tileSubtitle = it }, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt index 99329ba088d..e997b4e97b9 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt @@ -27,6 +27,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.R import io.homeassistant.companion.android.common.util.DisabledLocationHandler import io.homeassistant.companion.android.common.util.LocationPermissionInfoHandler +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.sensors.HealthConnectSensorManager import io.homeassistant.companion.android.settings.sensor.views.SensorDetailView import io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme @@ -141,7 +142,7 @@ class SensorDetailFragment : Fragment() { } healthPermissionsRequest?.launch(healthConnectPermissions.toSet()) } - Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> + sdkVersion.isAtLeast(Build.VERSION_CODES.R) -> if (it.permissions.size == 1 && it.permissions[0] == Manifest.permission.ACCESS_BACKGROUND_LOCATION ) { @@ -165,7 +166,7 @@ class SensorDetailFragment : Fragment() { continueYesCallback = { requestForServer = it.serverId permissionsRequest.launch( - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { it.permissions.toSet().minus( Manifest.permission.ACCESS_BACKGROUND_LOCATION, ).toTypedArray() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt index 6b0ecb37fb6..982aa9e58ad 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt @@ -24,6 +24,7 @@ import io.homeassistant.companion.android.common.sensors.BluetoothSensorManager import io.homeassistant.companion.android.common.sensors.NetworkSensorManager import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.DisabledLocationHandler +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.SensorDao import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType @@ -417,7 +418,7 @@ class SensorDetailViewModel @Inject constructor( return if (entries?.isNotEmpty() == true) { entries.map { try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { packageManager.getApplicationInfo(it, PackageManager.ApplicationInfoFlags.of(0)) } else { @Suppress("DEPRECATION") @@ -428,7 +429,7 @@ class SensorDetailViewModel @Inject constructor( } } } else { - val appInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + val appInfo = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { packageManager?.getInstalledApplications( PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong()), ) @@ -551,7 +552,7 @@ class SensorDetailViewModel @Inject constructor( // This is only called when we requested permissions to enable a sensor, so check if we // need to do another request, or if we have all permissions and should enable the sensor. if (results.keys.contains(Manifest.permission.ACCESS_FINE_LOCATION) && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.R + sdkVersion.isAtLeast(Build.VERSION_CODES.R) ) { permissionRequests.value = PermissionsDialog(serverId, arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt index 025a8b9cc54..cbd3c86474e 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.util.CHANNEL_SENSOR_WORKER +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.settings.SensorUpdateFrequencySetting import io.homeassistant.companion.android.util.compose.InfoNotification import io.homeassistant.companion.android.util.compose.RadioButtonRow @@ -53,7 +54,7 @@ fun SensorUpdateFrequencyView( onClick = { onSettingChanged(SensorUpdateFrequencySetting.FAST_ALWAYS) }, ) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { InfoNotification( infoString = R.string.sensor_update_notification, channelId = CHANNEL_SENSOR_WORKER, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt index af50db8b38d..4960862f111 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt @@ -40,6 +40,7 @@ import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.AreaRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.DeviceRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.IconDialogCompat import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.util.icondialog.getIconByMdiName @@ -63,7 +64,7 @@ class ManageShortcutsViewModel @Inject constructor( val app = application val canPinShortcuts = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && ShortcutManagerCompat.isRequestPinShortcutSupported(app) + sdkVersion.isAtLeast(Build.VERSION_CODES.O) && ShortcutManagerCompat.isRequestPinShortcutSupported(app) var pinnedShortcuts = ShortcutManagerCompat.getShortcuts(app, ShortcutManagerCompat.FLAG_MATCH_PINNED) .filter { !it.id.startsWith(AssistShortcutActivity.SHORTCUT_PREFIX) } .toMutableList() @@ -169,7 +170,7 @@ class ManageShortcutsViewModel @Inject constructor( updateDynamicShortcuts() Timber.d("We have ${dynamicShortcuts.size} dynamic shortcuts") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { Timber.d("Can we pin shortcuts: ${ShortcutManagerCompat.isRequestPinShortcutSupported(app)}") Timber.d("We have ${pinnedShortcuts.size} pinned shortcuts") } @@ -228,7 +229,7 @@ class ManageShortcutsViewModel @Inject constructor( if (isNewPinned) { Timber.d("Requesting to pin shortcut: $shortcutId") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { ShortcutManagerCompat.requestPinShortcut(app, shortcut, null) } } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt index 5248d7eed60..19aec5a3d21 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt @@ -19,6 +19,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.DisabledLocationHandler import io.homeassistant.companion.android.common.util.LocationPermissionInfoHandler +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.settings.addHelpMenuProvider import io.homeassistant.companion.android.settings.ssid.views.SsidView import io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme @@ -80,7 +81,7 @@ class SsidFragment : Fragment() { return } - val permissionsToCheck = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val permissionsToCheck = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION) } else { arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION) @@ -89,7 +90,7 @@ class SsidFragment : Fragment() { } private fun onRequestLocationPermission() { - val permissionsToCheck: Array = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val permissionsToCheck: Array = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION) } else { arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION) @@ -127,9 +128,9 @@ class SsidFragment : Fragment() { } private fun requestLocationPermission() { - val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + val permissions = if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) // Background location will be requested later - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + } else if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION) } else { arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION) @@ -140,7 +141,7 @@ class SsidFragment : Fragment() { private fun onPermissionsResult(results: Map) { if (results.keys.contains(Manifest.permission.ACCESS_FINE_LOCATION) && results[Manifest.permission.ACCESS_FINE_LOCATION] == true && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.R + sdkVersion.isAtLeast(Build.VERSION_CODES.R) ) { // For Android 11+ we MUST NOT request Background Location permission with fine or coarse // permissions as for Android 11 the background location request needs to be done separately diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt index 723d26f7bca..f9a5fad5604 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt @@ -59,6 +59,7 @@ import com.mikepenz.iconics.compose.Image import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.network.WifiHelper +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.util.compose.HaAlertInfo import io.homeassistant.companion.android.util.compose.HaAlertWarning import io.homeassistant.companion.android.util.plus @@ -118,7 +119,7 @@ fun SsidView( if ( activeSsid?.isNotBlank() == true && wifiSsids.none { it == activeSsid } && - (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || activeSsid !== WifiManager.UNKNOWN_SSID) + (!sdkVersion.isAtLeast(Build.VERSION_CODES.R) || activeSsid !== WifiManager.UNKNOWN_SSID) ) { item("ssid.suggestion") { Chip( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt index f52e82a39cd..1e944ea34f1 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt @@ -21,6 +21,7 @@ import androidx.core.content.getSystemService import io.homeassistant.companion.android.BuildConfig import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.util.CHANNEL_WEBSOCKET +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.settings.WebsocketSetting import io.homeassistant.companion.android.util.compose.HaAlertWarning import io.homeassistant.companion.android.util.compose.InfoNotification @@ -113,7 +114,7 @@ fun WebsocketSettingView( ) val uiManager = context.getSystemService() if (websocketSetting != WebsocketSetting.NEVER && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + sdkVersion.isAtLeast(Build.VERSION_CODES.O) && uiManager?.currentModeType != Configuration.UI_MODE_TYPE_TELEVISION ) { InfoNotification( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt index f28947c862f..528fa7d2d2c 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt @@ -10,6 +10,7 @@ import androidx.core.content.getSystemService import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.widget.ButtonWidgetDao import io.homeassistant.companion.android.database.widget.CameraWidgetDao import io.homeassistant.companion.android.database.widget.MediaPlayerControlsWidgetDao @@ -49,7 +50,7 @@ class ManageWidgetsViewModel @Inject constructor( } private fun checkSupportsAddingWidgets(): Boolean { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val appWidgetManager = getApplication().getSystemService() try { return appWidgetManager?.isRequestPinAppWidgetSupported ?: false diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt index 599ff3d46b9..165d4a8e5e9 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt @@ -8,6 +8,7 @@ import io.homeassistant.companion.android.common.data.prefs.NightModeTheme.DARK import io.homeassistant.companion.android.common.data.prefs.NightModeTheme.LIGHT import io.homeassistant.companion.android.common.data.prefs.NightModeTheme.SYSTEM import io.homeassistant.companion.android.common.data.prefs.PrefsRepository +import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -26,7 +27,7 @@ class NightModeManager @Inject constructor(private val prefsRepository: PrefsRep suspend fun getCurrentNightMode(): NightModeTheme { val nightMode = prefsRepository.getCurrentNightModeTheme() return if (nightMode == null) { - val nightModeThemeToSet = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + val nightModeThemeToSet = if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { SYSTEM } else { LIGHT diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt index 58313803d24..47198e4641a 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt @@ -10,6 +10,7 @@ import androidx.activity.ComponentActivity import androidx.annotation.ColorRes import androidx.core.content.ContextCompat import androidx.core.content.getSystemService +import io.homeassistant.companion.android.common.util.sdkVersion fun Context.getAttribute(attr: Int, fallbackAttr: Int): Int { val value = TypedValue() @@ -25,7 +26,7 @@ fun Context.getHexForColor(@ColorRes attr: Int): String { /** @return `true` if the device has an active network configured to reach the internet (not validated) */ fun Context.hasActiveConnection(): Boolean { val cm = getSystemService() ?: return false - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { cm.activeNetwork?.let { cm.getNetworkCapabilities(it)?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) } ?: false diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt index f299dc06bbd..f73ded03ab4 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt @@ -18,6 +18,7 @@ import androidx.core.app.NotificationManagerCompat import dagger.hilt.android.qualifiers.ApplicationContext import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.CHANNEL_DOWNLOADS +import io.homeassistant.companion.android.common.util.sdkVersion import java.io.File import java.io.FileOutputStream import java.text.SimpleDateFormat @@ -103,7 +104,7 @@ class DataUriDownloadManager @Inject constructor(@param:ApplicationContext priva generated } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { val contentValues = ContentValues().apply { put(MediaStore.Downloads.DISPLAY_NAME, fileName) put(MediaStore.Downloads.MIME_TYPE, mimetype) @@ -158,7 +159,7 @@ class DataUriDownloadManager @Inject constructor(@param:ApplicationContext priva } private fun createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationManager = NotificationManagerCompat.from(context) val channel = NotificationChannel( CHANNEL_DOWNLOADS, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt index cc1f8b65c35..c5f13e86cbb 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt @@ -7,21 +7,20 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.MultiplePermissionsState import com.google.accompanist.permissions.rememberMultiplePermissionsState import com.google.accompanist.permissions.rememberPermissionState +import io.homeassistant.companion.android.common.util.sdkVersion private val foregroundLocationPermissions: List = listOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, // TODO drop this requirement https://github.com/home-assistant/android/issues/5931 - if (Build.VERSION.SDK_INT >= - Build.VERSION_CODES.S - ) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { Manifest.permission.BLUETOOTH_CONNECT } else { Manifest.permission.BLUETOOTH }, ) val locationPermissions: List = foregroundLocationPermissions.run { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { this + Manifest.permission.ACCESS_BACKGROUND_LOCATION } else { this @@ -50,7 +49,7 @@ val locationPermissions: List = foregroundLocationPermissions.run { @OptIn(ExperimentalPermissionsApi::class) @Composable fun rememberLocationPermission(onPermissionResult: (Boolean) -> Unit): MultiplePermissionsState { - val backgroundPermissionState = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val backgroundPermissionState = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { rememberPermissionState( Manifest.permission.ACCESS_BACKGROUND_LOCATION, ) { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt index bcd0d257419..0fd0a8f902a 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt @@ -24,6 +24,7 @@ import androidx.webkit.WebSettingsCompat import androidx.webkit.WebViewFeature import io.homeassistant.companion.android.common.data.HomeAssistantApis import io.homeassistant.companion.android.common.data.prefs.NightModeTheme +import io.homeassistant.companion.android.common.util.sdkVersion import timber.log.Timber const val BLANK_URL = "about:blank" @@ -154,7 +155,7 @@ private fun WebView.defaultSettings() { @Suppress("DEPRECATION") private fun WebSettings.setNightModeTheme(nightModeTheme: NightModeTheme, uiMode: Int) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU && + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK) && WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY) ) { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt index e607c020c9c..6554f0f159c 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt @@ -8,6 +8,7 @@ import androidx.car.app.CarContext import androidx.car.app.model.Action import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.util.isAutomotive +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.launch.LaunchActivity import timber.log.Timber @@ -30,7 +31,7 @@ fun startNativeActivity(carContext: CarContext) { with(carContext) { // The app must indicate the default display to be used to avoid a SecurityException on newer // Android versions. See: https://developer.android.com/training/cars/platforms/releases#android-14 - val options = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + val options = if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { ActivityOptions.makeBasic() .setLaunchDisplayId(Display.DEFAULT_DISPLAY) .toBundle() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt index ecc92a958a2..46edc769377 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt @@ -12,6 +12,7 @@ import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.toAndroidIconCompat +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.settings.SettingsActivity import timber.log.Timber @@ -35,7 +36,7 @@ private fun startSettingsActivity(carContext: CarContext) { Timber.d("Starting settings activity") // The app must indicate the default display to be used to avoid a SecurityException on newer // Android versions. See: https://developer.android.com/training/cars/platforms/releases#android-14 - val options = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + val options = if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { ActivityOptions.makeBasic() .setLaunchDisplayId(Display.DEFAULT_DISPLAY) .toBundle() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt index 1f9faddb533..a5e2c220977 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt @@ -28,6 +28,7 @@ import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.CHANNEL_WEBSOCKET import io.homeassistant.companion.android.common.util.CHANNEL_WEBSOCKET_ISSUES +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.settings.SettingsDao import io.homeassistant.companion.android.database.settings.WebsocketSetting import io.homeassistant.companion.android.notifications.MessagingManager @@ -235,7 +236,7 @@ class WebsocketManager(appContext: Context, workerParams: WorkerParameters) : * @return `true` if the foreground service was started */ private suspend fun createNotification(): Boolean { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationChannel = NotificationChannel( CHANNEL_WEBSOCKET, applicationContext.getString(R.string.websocket_setting_name), @@ -279,7 +280,7 @@ class WebsocketManager(appContext: Context, workerParams: WorkerParameters) : ) .build() return try { - val type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + val type = if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { ServiceInfo.FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING } else { 0 @@ -290,7 +291,7 @@ class WebsocketManager(appContext: Context, workerParams: WorkerParameters) : if (e is CancellationException) return false Timber.e(e, "Unable to setForeground due to restrictions") - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { if (notificationManager.getNotificationChannel(CHANNEL_WEBSOCKET_ISSUES) == null) { val restrictedNotificationChannel = NotificationChannel( CHANNEL_WEBSOCKET_ISSUES, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt index cf4b57a77f1..9efe11d7c4d 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt @@ -111,6 +111,7 @@ import io.homeassistant.companion.android.common.util.initializePlayer import io.homeassistant.companion.android.common.util.isAutomotive import io.homeassistant.companion.android.common.util.jsonObjectOrNull import io.homeassistant.companion.android.common.util.runFragmentTransactionIfStateSafe +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.common.util.toJsonObject import io.homeassistant.companion.android.common.util.toJsonObjectOrNull import io.homeassistant.companion.android.database.authentication.Authentication @@ -365,7 +366,7 @@ class WebViewActivity : override fun onCreate(savedInstanceState: Bundle?) { if ( intent.extras?.containsKey(EXTRA_SHOW_WHEN_LOCKED) == true && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) ) { // Allow showing this on the lock screen when using device controls panel setShowWhenLocked(intent.extras?.getBoolean(EXTRA_SHOW_WHEN_LOCKED) ?: false) @@ -675,7 +676,7 @@ class WebViewActivity : } setDownloadListener { url, _, contentDisposition, mimetype, _ -> - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q || + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q) || ActivityCompat.checkSelfPermission( context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, @@ -783,7 +784,7 @@ class WebViewActivity : } } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val webviewPackage = WebViewCompat.getCurrentWebViewPackage(this) Timber.d( "Current webview package ${webviewPackage?.packageName} and version ${webviewPackage?.versionName}", @@ -1364,7 +1365,7 @@ class WebViewActivity : * devices the permission does not exist and no action is taken. */ private fun maybeRequestLocalNetworkPermission() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.CINNAMON_BUN) return + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return if (ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_LOCAL_NETWORK, @@ -1603,7 +1604,7 @@ class WebViewActivity : videoHeight = decor.height val bounds = Rect(0, 0, 1920, 1080) if (isVideoFullScreen or isExoFullScreen) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val mPictureInPictureParamsBuilder = PictureInPictureParams.Builder() mPictureInPictureParamsBuilder.setAspectRatio( Rational( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt b/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt index 2524cc2811a..d5c5fef21bf 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt @@ -46,6 +46,7 @@ import dev.chrisbanes.haze.materials.HazeMaterials import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.compose.theme.HATheme import io.homeassistant.companion.android.common.data.prefs.NightModeTheme +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.frontend.permissions.NotificationPermissionPrompt import io.homeassistant.companion.android.util.compose.media.player.HAMediaPlayer import io.homeassistant.companion.android.util.compose.webview.HAWebView @@ -71,7 +72,7 @@ internal fun WebViewContentScreen( nightModeTheme: NightModeTheme? = null, statusBarColor: Color? = null, backgroundColor: Color? = null, - supportsNotificationPermission: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU, + supportsNotificationPermission: Boolean = sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU), ) { HATheme { Scaffold( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt index 1341bcac4aa..dc615f82e7b 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt @@ -31,6 +31,7 @@ import io.homeassistant.companion.android.common.data.integration.Action import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.util.MapAnySerializer import io.homeassistant.companion.android.common.util.kotlinJsonMapper +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.widget.ButtonWidgetDao import io.homeassistant.companion.android.database.widget.ButtonWidgetEntity import io.homeassistant.companion.android.database.widget.WidgetBackgroundType @@ -358,7 +359,7 @@ class ButtonWidgetConfigureActivity : BaseWidgetConfigureActivity= Build.VERSION_CODES.O && + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O) && selectedServerId != null && ( widgetConfigAction in actions[selectedServerId].orEmpty().keys || diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/camera/CameraWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/camera/CameraWidgetConfigureActivity.kt index d321c420358..d16b57a9c5d 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/camera/CameraWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/camera/CameraWidgetConfigureActivity.kt @@ -18,6 +18,7 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.integration.IntegrationDomains.CAMERA_DOMAIN import io.homeassistant.companion.android.common.data.integration.IntegrationDomains.IMAGE_DOMAIN +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.widget.CameraWidgetDao import io.homeassistant.companion.android.database.widget.CameraWidgetEntity import io.homeassistant.companion.android.database.widget.WidgetTapAction @@ -72,7 +73,7 @@ class CameraWidgetConfigureActivity : BaseWidgetConfigureActivity= Build.VERSION_CODES.O && isValidServerId() && selectedEntity != null) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O) && isValidServerId() && selectedEntity != null) { requestWidgetCreation() } else { showAddWidgetError() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/entity/EntityWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/entity/EntityWidgetConfigureActivity.kt index 55609010abd..7ca03bf4fda 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/entity/EntityWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/entity/EntityWidgetConfigureActivity.kt @@ -24,6 +24,7 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.integration.EntityExt import io.homeassistant.companion.android.common.data.integration.friendlyName +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.widget.StaticWidgetDao import io.homeassistant.companion.android.database.widget.StaticWidgetEntity import io.homeassistant.companion.android.database.widget.WidgetBackgroundType @@ -86,7 +87,7 @@ class EntityWidgetConfigureActivity : BaseWidgetConfigureActivity= Build.VERSION_CODES.O && + sdkVersion.isAtLeast(Build.VERSION_CODES.O) && isValidServerId() ) { requestWidgetCreation() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/mediaplayer/MediaPlayerControlsWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/mediaplayer/MediaPlayerControlsWidgetConfigureActivity.kt index 797300c97a1..8eeb5e49263 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/mediaplayer/MediaPlayerControlsWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/mediaplayer/MediaPlayerControlsWidgetConfigureActivity.kt @@ -16,6 +16,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.integration.IntegrationDomains.MEDIA_PLAYER_DOMAIN +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.widget.MediaPlayerControlsWidgetDao import io.homeassistant.companion.android.database.widget.MediaPlayerControlsWidgetEntity import io.homeassistant.companion.android.database.widget.WidgetBackgroundType @@ -75,7 +76,7 @@ class MediaPlayerControlsWidgetConfigureActivity : lifecycleScope.launch { if (requestLauncherSetup) { if ( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + sdkVersion.isAtLeast(Build.VERSION_CODES.O) && isValidServerId() && binding.widgetTextConfigEntityId.text.split(",").any { entities[selectedServerId!!].orEmpty().any { e -> e.entityId == it.trim() } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt index 5e4a746f7cc..114f6bde032 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt @@ -15,6 +15,7 @@ import androidx.core.widget.doAfterTextChanged import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.common.R as commonR +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.widget.TemplateWidgetDao import io.homeassistant.companion.android.database.widget.TemplateWidgetEntity import io.homeassistant.companion.android.database.widget.WidgetBackgroundType @@ -146,7 +147,7 @@ class TemplateWidgetConfigureActivity : BaseWidgetConfigureActivity= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { lifecycleScope.launch { requestWidgetCreation() } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt index be80a119255..7e265046eb2 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt @@ -44,6 +44,7 @@ import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.websocket.impl.entities.AreaRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.DeviceRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.database.widget.WidgetBackgroundType import io.homeassistant.companion.android.settings.widgets.ManageWidgetsViewModel @@ -119,7 +120,7 @@ class TodoWidgetConfigureActivity : BaseActivity() { lifecycleScope.launch { if (intent.extras?.getBoolean(ManageWidgetsViewModel.CONFIGURE_REQUEST_LAUNCHER, false) == true) { if ( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + sdkVersion.isAtLeast(Build.VERSION_CODES.O) && viewModel.isValidSelection() ) { requestPinWidget() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetState.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetState.kt index 9316fa397e6..c9bd69b6864 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetState.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetState.kt @@ -12,6 +12,7 @@ import androidx.glance.material.ColorProviders import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.integration.friendlyName import io.homeassistant.companion.android.common.data.websocket.impl.entities.GetTodosResponse.TodoItem.Companion.COMPLETED_STATUS +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.widget.TodoWidgetEntity import io.homeassistant.companion.android.database.widget.WidgetBackgroundType import io.homeassistant.companion.android.util.compose.HomeAssistantGlanceTheme @@ -33,7 +34,7 @@ internal data class TodoItemState(val uid: String?, val name: String, val done: internal sealed interface TodoState { val backgroundType: WidgetBackgroundType - get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + get() = if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { WidgetBackgroundType.DYNAMICCOLOR } else { WidgetBackgroundType.DAYNIGHT diff --git a/app/src/minimal/kotlin/io/homeassistant/companion/android/location/LocationProvider.kt b/app/src/minimal/kotlin/io/homeassistant/companion/android/location/LocationProvider.kt index 2379fc1e6f1..67330761f9e 100644 --- a/app/src/minimal/kotlin/io/homeassistant/companion/android/location/LocationProvider.kt +++ b/app/src/minimal/kotlin/io/homeassistant/companion/android/location/LocationProvider.kt @@ -5,12 +5,12 @@ import android.content.Context import android.location.Location import android.location.LocationManager import android.os.Build -import android.os.Build.VERSION.SDK_INT import android.os.CancellationSignal import androidx.annotation.RequiresPermission import androidx.core.content.ContextCompat import androidx.core.location.LocationManagerCompat import io.homeassistant.companion.android.common.util.instant +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.sensors.GeocodeSensorManager.Companion.LOCATION_OUTDATED_THRESHOLD import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine @@ -18,7 +18,7 @@ import kotlin.time.Clock import kotlin.time.ExperimentalTime import timber.log.Timber -private val provider: String = if (SDK_INT >= Build.VERSION_CODES.S) { +private val provider: String = if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { LocationManager.FUSED_PROVIDER } else { LocationManager.GPS_PROVIDER diff --git a/app/src/test/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManagerTest.kt b/app/src/test/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManagerTest.kt index f01c7341882..3ba8e430a6a 100644 --- a/app/src/test/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManagerTest.kt +++ b/app/src/test/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManagerTest.kt @@ -7,6 +7,8 @@ import io.homeassistant.companion.android.common.data.integration.IntegrationRep import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.NotificationStatusProvider import io.homeassistant.companion.android.common.util.PermissionChecker +import io.homeassistant.companion.android.common.util.SdkVersionProvider +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.settings.SensorUpdateFrequencySetting import io.homeassistant.companion.android.database.settings.Setting import io.homeassistant.companion.android.database.settings.SettingsDao @@ -22,6 +24,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertInstanceOf @@ -50,17 +53,22 @@ class PermissionManagerTest { coEvery { serverManager.integrationRepository(serverId) } returns integrationRepository } + @AfterEach + fun tearDown() { + sdkVersion = SdkVersionProvider { false } + } + private fun createManager( hasFcmPushSupport: Boolean = false, sdkInt: Int = 0, ): PermissionManager { + sdkVersion = SdkVersionProvider { api -> sdkInt >= api } return PermissionManager( serverManager = serverManager, settingsDao = settingsDao, fcmSupport = hasFcmPushSupport, notificationStatusProvider = notificationStatusProvider, permissionChecker = permissionChecker, - sdkInt = sdkInt, ) } diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt index 2cb7c6a3da0..b34a3d17f03 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt @@ -13,6 +13,7 @@ import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.sensors.SensorReceiverBase import io.homeassistant.companion.android.common.sensors.SensorUpdateReceiver import io.homeassistant.companion.android.common.util.CHANNEL_BEACON_MONITOR +import io.homeassistant.companion.android.common.util.sdkVersion import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -79,7 +80,7 @@ class MonitoringManager { val builder = NotificationCompat.Builder(context, CHANNEL_BEACON_MONITOR) builder.setSmallIcon(R.drawable.ic_stat_ic_notification) builder.setContentTitle(context.getString(R.string.beacon_scanning)) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val channel = NotificationChannel( CHANNEL_BEACON_MONITOR, diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt index 243445c6fd3..7caf90de674 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.painterResource import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.toBitmap +import io.homeassistant.companion.android.common.util.sdkVersion /** * Loads a drawable as a Compose [Painter], with fallback support for [AdaptiveIconDrawable]. @@ -38,7 +39,7 @@ fun adaptiveIconPainterResource(@DrawableRes id: Int): Painter { val theme = LocalContext.current.theme val adaptivePainter: Painter? = remember(id, resources, theme) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return@remember null + if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O)) return@remember null val drawable = ResourcesCompat.getDrawable(resources, id, theme) as? AdaptiveIconDrawable ?: return@remember null BitmapPainter(drawable.toBitmap().asImageBitmap()) diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt index d04a167faee..639dbe14fb9 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt @@ -17,6 +17,7 @@ import io.homeassistant.companion.android.common.data.websocket.impl.entities.Co import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryOptions import io.homeassistant.companion.android.common.util.LocalDateTimeSerializer import io.homeassistant.companion.android.common.util.MapAnySerializer +import io.homeassistant.companion.android.common.util.sdkVersion import java.time.LocalDateTime import java.time.ZoneOffset import java.time.ZonedDateTime @@ -1204,7 +1205,7 @@ fun Entity.friendlyState( } } } - if (friendlyState == state && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (friendlyState == state && sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { try { val stateInMillis = ZonedDateTime.parse(state, DateTimeFormatter.ISO_OFFSET_DATE_TIME) .toInstant() diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt index 09853d52c8e..b4805d97bac 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt @@ -4,6 +4,7 @@ import android.net.ConnectivityManager import android.net.NetworkCapabilities import android.net.wifi.WifiManager import android.os.Build +import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject @Suppress("DEPRECATION") @@ -25,7 +26,7 @@ class WifiHelperImpl @Inject constructor( val formattedBssid = getWifiBssid() return ( formattedSsid != null && - (Build.VERSION.SDK_INT < Build.VERSION_CODES.R || formattedSsid !== WifiManager.UNKNOWN_SSID) && + (!sdkVersion.isAtLeast(Build.VERSION_CODES.R) || formattedSsid !== WifiManager.UNKNOWN_SSID) && formattedSsid in networks ) || ( diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt index 558fd0a0cd4..8cbbce3d1a6 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt @@ -8,6 +8,7 @@ import androidx.core.app.NotificationManagerCompat import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.cancelGroupIfNeeded +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.notification.NotificationDao import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -35,7 +36,7 @@ class NotificationDeleteReceiver : BroadcastReceiver() { @Suppress("UNCHECKED_CAST") override fun onReceive(context: Context, intent: Intent) { - val hashData = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + val hashData = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { intent.getSerializableExtra(EXTRA_DATA, HashMap::class.java) } else { @Suppress("DEPRECATION") diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt index faf15eaa6ec..a6176aaa5b6 100755 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt @@ -26,6 +26,7 @@ import com.vdurmont.emoji.EmojiParser import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.util.CHANNEL_GENERAL import io.homeassistant.companion.android.common.util.cancel +import io.homeassistant.companion.android.common.util.sdkVersion import java.util.Locale import timber.log.Timber @@ -82,7 +83,7 @@ fun handleChannel( } // Since android Oreo notification channel is needed. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val channel = NotificationChannel( channelID, channelName, @@ -143,7 +144,7 @@ fun handleChannelSound(context: Context, channel: NotificationChannel) { } fun setChannelLedColor(context: Context, data: Map, channel: NotificationChannel) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val ledColor = data[NotificationData.LED_COLOR] if (!ledColor.isNullOrBlank()) { channel.enableLights(true) @@ -153,7 +154,7 @@ fun setChannelLedColor(context: Context, data: Map, channel: Not } fun setChannelVibrationPattern(data: Map, channel: NotificationChannel) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val vibrationPattern = data[NotificationData.VIBRATION_PATTERN] val arrVibrationPattern = parseVibrationPattern(vibrationPattern) if (arrVibrationPattern.isNotEmpty()) { diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt index 2f527f05671..789b5dfa870 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt @@ -9,6 +9,7 @@ import android.os.Process import androidx.annotation.RequiresApi import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR +import io.homeassistant.companion.android.common.util.sdkVersion import java.math.RoundingMode import timber.log.Timber @@ -100,7 +101,7 @@ abstract class AppSensorManagerBase : SensorManager { override suspend fun getAvailableSensors(context: Context): List { return when { - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) -> + (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) -> listOf( currentVersion, app_rx_gb, @@ -135,7 +136,7 @@ abstract class AppSensorManagerBase : SensorManager { updateImportanceCheck(context) val usageStatsManager = context.getSystemService()!! updateAppInactive(context, usageStatsManager) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { updateAppStandbyBucket(context, usageStatsManager) } } diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt index 5d13946832e..c5c9f6b84e0 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt @@ -8,6 +8,7 @@ import androidx.annotation.RequiresApi import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.toSensorsWithAttributes import java.util.concurrent.ConcurrentHashMap @@ -51,7 +52,7 @@ class AudioSensorManager : SensorManager { commonR.string.sensor_description_mic_muted, "mdi:microphone-off", updateType = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { SensorManager.BasicSensor.UpdateType.INTENT } else { SensorManager.BasicSensor.UpdateType.WORKER @@ -71,7 +72,7 @@ class AudioSensorManager : SensorManager { commonR.string.sensor_description_speakerphone, "mdi:volume-high", updateType = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { SensorManager.BasicSensor.UpdateType.INTENT } else { SensorManager.BasicSensor.UpdateType.WORKER @@ -164,7 +165,7 @@ class AudioSensorManager : SensorManager { musicActive, volAlarm, volCall, volMusic, volRing, volNotification, volSystem, volDTMF, ) - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { allSupportedSensors.plus(volAccessibility) } else { allSupportedSensors @@ -190,7 +191,7 @@ class AudioSensorManager : SensorManager { updateVolumeNotification(context, audioManager) updateVolumeSystem(context, audioManager) updateVolumeDTMF(context, audioManager) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { updateVolumeAccessibility(context, audioManager) } } @@ -397,7 +398,7 @@ class AudioSensorManager : SensorManager { } val current = audioManager.getStreamVolume(streamType) - val min = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + val min = if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { audioManager.getStreamMinVolume(streamType) } else { 0 diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt index 5d4193a7279..82de885ee8d 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt @@ -10,6 +10,7 @@ import androidx.core.content.ContextCompat import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.sdkVersion import java.math.RoundingMode import kotlin.math.floor import timber.log.Timber @@ -146,9 +147,9 @@ class BatterySensorManager : SensorManager { ) override suspend fun getAvailableSensors(context: Context): List { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { defaultSensorList.plus(listOf(remainingChargeTime, batteryCycles)) - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + } else if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { defaultSensorList.plus(remainingChargeTime) } else { defaultSensorList @@ -184,10 +185,10 @@ class BatterySensorManager : SensorManager { updateBatteryHealth(context, intent) updateBatteryTemperature(context, intent) updateBatteryPower(context, intent) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { updateRemainingChargeTime(context) } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { updateBatteryCycles(context, intent) } } @@ -447,7 +448,7 @@ class BatterySensorManager : SensorManager { private suspend fun getBatteryCurrent(context: Context, batteryManager: BatteryManager): Float? { val current = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW) return if ( - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && current != Int.MIN_VALUE) || + (sdkVersion.isAtLeast(Build.VERSION_CODES.P) && current != Int.MIN_VALUE) || current != 0 ) { val dividerSetting = getNumberSetting( diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt index e8fc251981d..6923489f2cb 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt @@ -16,6 +16,7 @@ import io.homeassistant.companion.android.common.bluetooth.ble.MonitoringManager import io.homeassistant.companion.android.common.bluetooth.ble.TransmitterManager import io.homeassistant.companion.android.common.bluetooth.ble.name import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.DatabaseEntryPoint import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType @@ -175,14 +176,14 @@ class BluetoothSensorManager : SensorManager { @SuppressLint("InlinedApi") override fun requiredPermissions(context: Context, sensorId: String): Array { return when { - (sensorId == bleTransmitter.id && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> { + (sensorId == bleTransmitter.id && sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.BLUETOOTH_ADVERTISE, Manifest.permission.BLUETOOTH_CONNECT, ) } - (sensorId == beaconMonitor.id && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) -> { + (sensorId == beaconMonitor.id && !sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) -> { arrayOf( Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, @@ -191,7 +192,7 @@ class BluetoothSensorManager : SensorManager { ) } - (sensorId == beaconMonitor.id && Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) -> { + (sensorId == beaconMonitor.id && !sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, @@ -201,7 +202,7 @@ class BluetoothSensorManager : SensorManager { ) } - (sensorId == beaconMonitor.id && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> { + (sensorId == beaconMonitor.id && sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, @@ -211,7 +212,7 @@ class BluetoothSensorManager : SensorManager { ) } - (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) -> { + (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.BLUETOOTH_CONNECT, ) diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt index 95f228f0a69..97f209181f9 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt @@ -9,6 +9,7 @@ import android.provider.Settings.Global.getInt import android.telephony.TelephonyManager import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR +import io.homeassistant.companion.android.common.util.sdkVersion class MobileDataManager : SensorManager { @@ -43,7 +44,7 @@ class MobileDataManager : SensorManager { } override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (sensorId == mobileDataRoaming.id || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return if (sensorId == mobileDataRoaming.id || sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { arrayOf(Manifest.permission.READ_PHONE_STATE) } else { arrayOf() @@ -72,9 +73,9 @@ class MobileDataManager : SensorManager { var enabled = false val telephonyManager = context.applicationContext.getSystemService() if (telephonyManager?.simState == TelephonyManager.SIM_STATE_READY) { - enabled = if (sensor.id == mobileDataRoaming.id && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + enabled = if (sensor.id == mobileDataRoaming.id && sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { telephonyManager.isDataRoamingEnabled - } else if (sensor.id == mobileDataState.id && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + } else if (sensor.id == mobileDataState.id && sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { telephonyManager.isDataEnabled } else { getInt(context.contentResolver, settingKey, 0) == 1 diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt index 7b1a353dcfa..1e7af74c6f4 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt @@ -14,6 +14,7 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN import io.homeassistant.companion.android.common.util.getStringOrElse +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.common.util.toJsonObjectOrNull import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType @@ -176,7 +177,7 @@ class NetworkSensorManager : SensorManager { arrayOf() } - Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> { + sdkVersion.isAtLeast(Build.VERSION_CODES.Q) -> { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, @@ -338,7 +339,7 @@ class NetworkSensorManager : SensorManager { deviceIp = if (conInfo == null || (conInfo.networkId == -1 && conInfo.linkSpeed == -1)) { "" } else { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { val connectivityManager = context.applicationContext.getSystemService() connectivityManager?.activeNetwork?.let { // Get the IPv4 address without prefix length @@ -622,19 +623,18 @@ class NetworkSensorManager : SensorManager { } /** Get WiFi connection info (without location data such as (B)SSID on Android >=S) */ - private fun getWifiConnectionInfo(context: Context): WifiInfo? = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - val connectivityManager = context.applicationContext.getSystemService() - connectivityManager?.activeNetwork?.let { - val info = connectivityManager.getNetworkCapabilities(it)?.transportInfo + private fun getWifiConnectionInfo(context: Context): WifiInfo? = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + val connectivityManager = context.applicationContext.getSystemService() + connectivityManager?.activeNetwork?.let { + val info = connectivityManager.getNetworkCapabilities(it)?.transportInfo - // If WifiInfo is null default to the deprecated method as a fix for some devices that may return null - @Suppress("DEPRECATION") - return@let info as? WifiInfo - ?: context.applicationContext.getSystemService()?.connectionInfo - } - } else { + // If WifiInfo is null default to the deprecated method as a fix for some devices that may return null @Suppress("DEPRECATION") - context.applicationContext.getSystemService()?.connectionInfo + return@let info as? WifiInfo + ?: context.applicationContext.getSystemService()?.connectionInfo } + } else { + @Suppress("DEPRECATION") + context.applicationContext.getSystemService()?.connectionInfo + } } diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt index 3217d3569d5..9c235e28513 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt @@ -14,6 +14,7 @@ import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.sdkVersion import timber.log.Timber class PhoneStateSensorManager : SensorManager { @@ -127,7 +128,7 @@ class PhoneStateSensorManager : SensorManager { override suspend fun getAvailableSensors(context: Context): List { return when { ( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && + sdkVersion.isAtLeast(Build.VERSION_CODES.Q) && context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) ) -> listOf( @@ -141,7 +142,7 @@ class PhoneStateSensorManager : SensorManager { ) ( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && + sdkVersion.isAtLeast(Build.VERSION_CODES.N) && context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) ) -> listOf(phoneState, sim_1, sim_2, sim1DataNetworkType, sim2DataNetworkType) @@ -160,11 +161,11 @@ class PhoneStateSensorManager : SensorManager { checkPhoneState(context) updateSimSensor(context, 0) updateSimSensor(context, 1) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { updateSignalStrength(context, 0) updateSignalStrength(context, 1) } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { updateDataNetworkType(context, 0) updateDataNetworkType(context, 1) } @@ -234,7 +235,7 @@ class PhoneStateSensorManager : SensorManager { displayName = info.displayName?.toString() ?: info.carrierName.toString() attrs["carrier name"] = info.carrierName attrs["iso country code"] = info.countryIso - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { attrs["carrier id"] = info.carrierId attrs["mcc"] = info.mccString.toString() attrs["mnc"] = info.mncString.toString() diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt index 163f2626ffe..2c9d5949f83 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt @@ -16,6 +16,7 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.AnySerializer import io.homeassistant.companion.android.common.util.kotlinJsonMapper +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.Attribute import io.homeassistant.companion.android.database.sensor.SensorDao import io.homeassistant.companion.android.database.sensor.SensorSetting @@ -90,14 +91,14 @@ interface SensorManager { fun checkUsageStatsPermission(context: Context): Boolean { val pm = context.packageManager - val appInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + val appInfo = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { pm.getApplicationInfo(context.packageName, PackageManager.ApplicationInfoFlags.of(0)) } else { @Suppress("DEPRECATION") pm.getApplicationInfo(context.packageName, 0) } val appOpsManager = context.getSystemService() - val mode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val mode = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { appOpsManager?.unsafeCheckOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, appInfo.uid, appInfo.packageName) } else { @Suppress("DEPRECATION") diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt index 0f36e050b2a..17961852b48 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt @@ -19,6 +19,7 @@ import io.homeassistant.companion.android.common.data.integration.SensorRegistra import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.GetConfigResponse import io.homeassistant.companion.android.common.util.CHANNEL_SENSOR_SYNC +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.DatabaseEntryPoint import io.homeassistant.companion.android.database.sensor.SensorDao import io.homeassistant.companion.android.database.sensor.SensorWithAttributes @@ -440,7 +441,7 @@ abstract class SensorReceiverBase : BroadcastReceiver() { } private fun createNotificationChannel(context: Context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationManager = context.getSystemService() ?: return var notificationChannel = notificationManager.getNotificationChannel(CHANNEL_SENSOR_SYNC) diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt index 5cd3a542d17..a55f0a77327 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt @@ -13,6 +13,7 @@ import androidx.work.WorkerParameters import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.CHANNEL_SENSOR_WORKER +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.DatabaseEntryPoint import java.lang.IllegalStateException import kotlinx.coroutines.Dispatchers @@ -51,7 +52,7 @@ abstract class SensorWorkerBase(val appContext: Context, workerParams: WorkerPar val foregroundInfo = ForegroundInfo( NOTIFICATION_ID, notification, - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC } else { 0 @@ -89,7 +90,7 @@ abstract class SensorWorkerBase(val appContext: Context, workerParams: WorkerPar } protected fun createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationChannel = NotificationChannel( CHANNEL_SENSOR_WORKER, appContext.getString(commonR.string.sensor_updates), diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt index 3f207892177..dd836b3a15b 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt @@ -10,6 +10,7 @@ import android.hardware.SensorManager.SENSOR_DELAY_NORMAL import android.os.Build import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR +import io.homeassistant.companion.android.common.util.sdkVersion import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -51,7 +52,7 @@ class StepsSensorManager : private lateinit var mySensorManager: android.hardware.SensorManager override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf(Manifest.permission.ACTIVITY_RECOGNITION) } else { emptyArray() diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt index 32dccba9729..097108bbd22 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt @@ -10,7 +10,6 @@ import android.content.Intent import android.content.pm.PackageManager import android.graphics.Color import android.location.LocationManager -import android.os.Build.VERSION import android.os.Build.VERSION_CODES import android.provider.Settings import androidx.appcompat.app.AlertDialog @@ -30,7 +29,7 @@ object DisabledLocationHandler { fun isLocationEnabled(context: Context): Boolean { val lm: LocationManager = context.getSystemService() ?: return false - return if (VERSION.SDK_INT >= VERSION_CODES.P) { + return if (sdkVersion.isAtLeast(VERSION_CODES.P)) { lm.isLocationEnabled } else { lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) || @@ -94,7 +93,7 @@ object DisabledLocationHandler { val parameters = settings.joinToString(separator = "\n") { "- $it" } - if (VERSION.SDK_INT >= VERSION_CODES.O) { + if (sdkVersion.isAtLeast(VERSION_CODES.O)) { val channel = NotificationChannel( CHANNEL_LOCATION_DISABLED, context.applicationContext.getString(commonR.string.location_warn_channel), diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt index bfcef1690ec..3e707780655 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt @@ -126,7 +126,7 @@ private fun createDataSourceFactory( private fun buildHttpEngineFactory(context: Context): DataSource.Factory? { // https://developer.android.com/reference/android/net/http/HttpEngine // Added in API level 34 also in S Extensions 7 - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.R) && SdkExtensions.getExtensionVersion(Build.VERSION_CODES.S) >= 7 ) { // Use Platform embedded Cronet via android.net.http.HttpEngine diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt index fb8b023bb37..afb08e3472f 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt @@ -32,7 +32,7 @@ fun cancelNotificationGroupIfNeeded( id: Int, cancel: (String, Int) -> Unit, ): Boolean { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { Timber.d("Cancel notification with tag \"$tag\" and id \"$id\"") val currentActiveNotifications = notificationManager.activeNotifications diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt b/common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt index 43beae6a036..81988e8afab 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt @@ -10,6 +10,7 @@ import androidx.core.app.NotificationManagerCompat import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.CHANNEL_DATABASE +import io.homeassistant.companion.android.common.util.sdkVersion private const val NOTIFICATION_ID = 45 private const val TAG = "AppDatabase" @@ -27,7 +28,7 @@ internal fun Cursor.map(transform: (Cursor) -> T): List { } private fun createNotificationChannel(context: Context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationManager = context.getSystemService()!! var notificationChannel = diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt b/common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt index acc636914ee..70906975b55 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt @@ -30,6 +30,7 @@ import io.homeassistant.companion.android.common.data.prefs.WearPrefsRepositoryI import io.homeassistant.companion.android.common.util.MtlsAwareDataSourceFactory import io.homeassistant.companion.android.common.util.di.SuspendProvider import io.homeassistant.companion.android.common.util.getSharedPreferencesSuspend +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.common.util.tts.AndroidTextToSpeechEngine import io.homeassistant.companion.android.common.util.tts.TextToSpeechClient import io.homeassistant.companion.android.di.qualifiers.NamedDeviceId @@ -126,7 +127,7 @@ internal abstract class DataModule { @Provides @NamedOsVersion @Singleton - fun provideDeviceOsVersion() = Build.VERSION.SDK_INT.toString() + fun provideDeviceOsVersion() = sdkVersion.toString() @SuppressLint("HardwareIds") @Provides diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt index 35be7afad47..fe26f6645a9 100644 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt @@ -18,6 +18,7 @@ import io.homeassistant.companion.android.common.data.keychain.NamedKeyStore import io.homeassistant.companion.android.common.sensors.AudioSensorManager import io.homeassistant.companion.android.common.util.HAStrictMode import io.homeassistant.companion.android.common.util.configureComposeDiagnosticStackTrace +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.complications.ComplicationReceiver import io.homeassistant.companion.android.sensors.SensorReceiver import javax.inject.Inject @@ -40,14 +41,14 @@ open class HomeAssistantApplication : Application() { Timber.plant(Timber.DebugTree()) super.onCreate() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + if (sdkVersion.isAtLeast(Build.VERSION_CODES.S) && BuildConfig.DEBUG && !BuildConfig.NO_STRICT_MODE ) { HAStrictMode.enable() } - Timber.i("Running ${BuildConfig.VERSION_NAME} on SDK ${Build.VERSION.SDK_INT}") + Timber.i("Running ${BuildConfig.VERSION_NAME} on SDK $sdkVersion") configureComposeDiagnosticStackTrace(isDebug = BuildConfig.DEBUG) @@ -104,7 +105,7 @@ open class HomeAssistantApplication : Application() { ) // Listen for microphone mute changes - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { ContextCompat.registerReceiver( this, sensorReceiver, @@ -114,7 +115,7 @@ open class HomeAssistantApplication : Application() { } // Listen for speakerphone state changes - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { ContextCompat.registerReceiver( this, sensorReceiver, diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt index a03355f2675..bd27258b3b8 100644 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt @@ -16,6 +16,7 @@ import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.wear.protolayout.ActionBuilders import dagger.hilt.android.AndroidEntryPoint +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.home.views.DEEPLINK_PREFIX_SET_CAMERA_TILE import io.homeassistant.companion.android.home.views.DEEPLINK_PREFIX_SET_SHORTCUT_TILE import io.homeassistant.companion.android.home.views.DEEPLINK_PREFIX_SET_TEMPLATE_TILE @@ -182,7 +183,7 @@ class HomeActivity : } if ( intent.getBooleanExtra(EXTRA_FROM_ONBOARDING, false) && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && !NotificationManagerCompat.from(this@HomeActivity).areNotificationsEnabled() ) { permissionRequest.launch(Manifest.permission.POST_NOTIFICATIONS) diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt index af902ba9b5f..9d3ef870876 100644 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt @@ -22,6 +22,7 @@ import androidx.wear.compose.material3.SwitchButton import androidx.wear.compose.material3.Text import androidx.wear.tooling.preview.devices.WearDevices import io.homeassistant.companion.android.common.sensors.SensorManager +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.Sensor import io.homeassistant.companion.android.theme.getSwitchButtonColors import io.homeassistant.companion.android.util.batterySensorManager @@ -51,7 +52,7 @@ fun SensorUi( isGranted.forEach { if ( it.key == Manifest.permission.ACCESS_FINE_LOCATION && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && + sdkVersion.isAtLeast(Build.VERSION_CODES.R) && manager.requiredPermissions( context, basicSensor.id, @@ -66,7 +67,7 @@ fun SensorUi( } if ( it.key == Manifest.permission.BODY_SENSORS && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && manager.requiredPermissions(context, basicSensor.id).contains(Manifest.permission.BODY_SENSORS) && manager.requiredPermissions( context, diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt index b114ceca1b5..d53a5e70e8c 100755 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt @@ -5,6 +5,7 @@ import android.os.Build import android.provider.Settings import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager +import io.homeassistant.companion.android.common.util.sdkVersion import timber.log.Timber class BedtimeModeSensorManager : SensorManager { @@ -39,7 +40,7 @@ class BedtimeModeSensorManager : SensorManager { } override fun hasSensor(context: Context): Boolean { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.R + return sdkVersion.isAtLeast(Build.VERSION_CODES.R) } private suspend fun updateBedtimeMode(context: Context) { diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt index b32ec555294..36fda81c453 100755 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt @@ -20,6 +20,7 @@ import androidx.health.services.client.data.UserActivityState import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.sdkVersion import java.time.Instant import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -102,7 +103,7 @@ class HealthServicesSensorManager : SensorManager { private val ioScope: CoroutineScope = CoroutineScope(Dispatchers.IO + Job()) - private val areHealthServicesSensorApisAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R + private val areHealthServicesSensorApisAvailable = sdkVersion.isAtLeast(Build.VERSION_CODES.R) override fun docsLink(): String { return "https://companion.home-assistant.io/docs/wear-os/sensors#health-services" diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt index 35d484eedf5..b865ce9d6ff 100755 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt @@ -17,6 +17,7 @@ import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.sdkVersion import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -60,7 +61,7 @@ class HeartRateSensorManager : } override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { arrayOf(Manifest.permission.BODY_SENSORS, Manifest.permission.BODY_SENSORS_BACKGROUND) } else { arrayOf(Manifest.permission.BODY_SENSORS) diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt index 93412e26429..af140343f7c 100644 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt @@ -24,6 +24,7 @@ import androidx.wear.protolayout.material.layouts.PrimaryLayout import androidx.wear.tiles.RequestBuilders import io.homeassistant.companion.android.R import io.homeassistant.companion.android.common.R as commonR +import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.home.HomeActivity import io.homeassistant.companion.android.splash.SplashActivity @@ -32,7 +33,7 @@ const val MODIFIER_CLICK_REFRESH = "refresh" /** Performs a [VibrationEffect.EFFECT_CLICK] or equivalent on older Android versions */ fun hapticClick(context: Context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { val vibratorManager = context.getSystemService() val vibrator = vibratorManager?.defaultVibrator vibrator?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) From f05b1f45c866defb252a201955181012a74d6f77 Mon Sep 17 00:00:00 2001 From: Timothy <6560631+TimoPtr@users.noreply.github.com> Date: Thu, 21 May 2026 11:25:26 +0200 Subject: [PATCH 3/7] Remove ObsoleteAPI lint suppress --- app/lint-baseline.xml | 105 +- .../android/sensors/CarSensorManager.kt | 2 - .../todo/TodoWidgetConfigureActivity.kt | 3 - automotive/lint-baseline.xml | 1152 +++-------------- common/lint-baseline.xml | 88 +- wear/lint-baseline.xml | 4 +- 6 files changed, 207 insertions(+), 1147 deletions(-) diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml index 783bf1ffe4a..73072ef1c7a 100644 --- a/app/lint-baseline.xml +++ b/app/lint-baseline.xml @@ -1,5 +1,5 @@ - + @@ -19,7 +19,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -30,7 +30,7 @@ errorLine2=" ^"> @@ -41,7 +41,7 @@ errorLine2=" ^"> @@ -52,7 +52,7 @@ errorLine2=" ^"> @@ -63,7 +63,7 @@ errorLine2=" ^"> @@ -74,7 +74,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -85,7 +85,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -107,7 +107,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -118,7 +118,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -129,7 +129,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -140,7 +140,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -393,7 +393,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -426,7 +426,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -525,7 +525,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -602,7 +602,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -661,28 +661,6 @@ column="45"/> - - - - - - - - @@ -701,7 +679,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1220,7 +1198,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -1231,7 +1209,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -1242,7 +1220,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1253,7 +1231,7 @@ errorLine2="^"> @@ -1264,7 +1242,7 @@ errorLine2="^"> @@ -1275,7 +1253,7 @@ errorLine2="^"> @@ -1594,7 +1572,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -1605,7 +1583,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -1616,7 +1594,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -1682,7 +1660,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -1704,7 +1682,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -1715,7 +1693,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -1726,7 +1704,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1737,7 +1715,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1748,7 +1726,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -1763,17 +1741,6 @@ column="9"/> - - - - @@ -1814,7 +1781,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt index b019e55953b..94411a545a6 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt @@ -1,6 +1,5 @@ package io.homeassistant.companion.android.sensors -import android.annotation.SuppressLint import android.content.Context import android.os.Build import androidx.car.app.hardware.common.CarValue @@ -219,7 +218,6 @@ class CarSensorManager : private lateinit var latestContext: Context - @SuppressLint("ObsoleteSdkInt") // Needed for app module (minSdk 21) but obsolete for automotive (minSdk 29) private val areCarSensorApisAvailable = sdkVersion.isAtLeast(Build.VERSION_CODES.O) private val isAutomotive get() = latestContext.isAutomotive() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt index 7e265046eb2..cfdd546af08 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt @@ -1,6 +1,5 @@ package io.homeassistant.companion.android.widgets.todo -import android.annotation.SuppressLint import android.appwidget.AppWidgetManager import android.content.Context import android.content.Intent @@ -115,7 +114,6 @@ class TodoWidgetConfigureActivity : BaseActivity() { } } - @SuppressLint("ObsoleteSdkInt") private fun onActionClick() { lifecycleScope.launch { if (intent.extras?.getBoolean(ManageWidgetsViewModel.CONFIGURE_REQUEST_LAUNCHER, false) == true) { @@ -133,7 +131,6 @@ class TodoWidgetConfigureActivity : BaseActivity() { } } - @SuppressLint("ObsoleteSdkInt") @RequiresApi(Build.VERSION_CODES.O) private fun requestPinWidget() { val context = this@TodoWidgetConfigureActivity diff --git a/automotive/lint-baseline.xml b/automotive/lint-baseline.xml index 60398f89b24..97ef8a96224 100644 --- a/automotive/lint-baseline.xml +++ b/automotive/lint-baseline.xml @@ -8,7 +8,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -19,7 +19,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -30,7 +30,7 @@ errorLine2=" ^"> @@ -41,7 +41,7 @@ errorLine2=" ^"> @@ -52,7 +52,7 @@ errorLine2=" ^"> @@ -63,7 +63,7 @@ errorLine2=" ^"> @@ -74,7 +74,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -85,7 +85,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -96,7 +96,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -107,7 +107,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -129,7 +129,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -140,7 +140,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -151,7 +151,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -338,7 +338,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> @@ -371,7 +371,7 @@ errorLine2=" ~~~~~~~~~~~"> @@ -382,7 +382,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -481,7 +481,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> @@ -558,7 +558,7 @@ errorLine2=" ~~~~~~~~~~~~~"> @@ -617,17 +617,6 @@ column="45"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + message="Unnecessary; `SDK_INT` is always >= 28" + errorLine1=" @RequiresApi(Build.VERSION_CODES.P)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/util/IgnoreViolationRules.kt" + line="210" + column="5"/> + message="Unnecessary; `SDK_INT` is always >= 28" + errorLine1=" @RequiresApi(Build.VERSION_CODES.P)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/util/IgnoreViolationRules.kt" + line="226" + column="5"/> + message="Unnecessary; `SDK_INT` is always >= 28" + errorLine1=" @RequiresApi(Build.VERSION_CODES.P)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/util/IgnoreViolationRules.kt" + line="249" + column="5"/> + message="Unnecessary; `SDK_INT` is always >= 28" + errorLine1=" @RequiresApi(Build.VERSION_CODES.P)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/util/IgnoreViolationRules.kt" + line="275" + column="5"/> + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1="@RequiresApi(Build.VERSION_CODES.O)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/util/compose/InfoNotification.kt" + line="23" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1="@RequiresApi(Build.VERSION_CODES.O)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/vehicle/MainVehicleScreen.kt" + line="45" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1=" @RequiresApi(Build.VERSION_CODES.O)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/vehicle/ManageAndroidAutoSettingsFragment.kt" + line="24" + column="5"/> + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1="@RequiresApi(Build.VERSION_CODES.O)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/vehicle/ManageAndroidAutoViewModel.kt" + line="31" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 25" + errorLine1="@RequiresApi(Build.VERSION_CODES.N_MR1)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsSettingsFragment.kt" + line="25" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 25" + errorLine1=" @RequiresApi(Build.VERSION_CODES.N_MR1)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsSettingsFragment.kt" + line="61" + column="5"/> + message="Unnecessary; `SDK_INT` is always >= 25" + errorLine1="@RequiresApi(Build.VERSION_CODES.N_MR1)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/shortcuts/views/ManageShortcutsView.kt" + line="49" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 25" + errorLine1="@RequiresApi(Build.VERSION_CODES.N_MR1)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/shortcuts/views/ManageShortcutsView.kt" + line="85" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 25" + errorLine1="@RequiresApi(Build.VERSION_CODES.N_MR1)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/shortcuts/views/ManageShortcutsView.kt" + line="352" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 25" + errorLine1="@RequiresApi(Build.VERSION_CODES.N_MR1)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/shortcuts/views/ManageShortcutsView.kt" + line="364" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 25" + errorLine1="@RequiresApi(Build.VERSION_CODES.N_MR1)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt" + line="57" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1="@RequiresApi(Build.VERSION_CODES.O)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/vehicle/MapVehicleScreen.kt" + line="36" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1=" @RequiresApi(Build.VERSION_CODES.O)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/notification/NotificationChannelFragment.kt" + line="23" + column="5"/> + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1="@RequiresApi(Build.VERSION_CODES.O)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/notification/views/NotificationChannelView.kt" + line="38" + column="1"/> + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1="@RequiresApi(Build.VERSION_CODES.O)" + errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/settings/notification/NotificationViewModel.kt" + line="17" + column="1"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + message="Unnecessary; `SDK_INT` is always >= 26" + errorLine1=" @RequiresApi(Build.VERSION_CODES.O)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + file="${:automotive*fullDebug*MAIN*sourceProvider*0*javaDir*5}/io/homeassistant/companion/android/widgets/todo/TodoWidgetConfigureActivity.kt" + line="135" + column="5"/> @@ -2364,7 +1528,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2905,7 +2069,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2916,7 +2080,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> @@ -2927,7 +2091,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -2949,7 +2113,7 @@ errorLine2="^"> @@ -2960,7 +2124,7 @@ errorLine2="^"> @@ -3279,7 +2443,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -3290,7 +2454,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> @@ -3301,7 +2465,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -3367,7 +2531,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -3389,7 +2553,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -3400,7 +2564,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -3411,7 +2575,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -3422,7 +2586,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -3433,7 +2597,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -3477,7 +2641,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -3488,7 +2652,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> diff --git a/common/lint-baseline.xml b/common/lint-baseline.xml index 59b91403b5c..170322e65b9 100644 --- a/common/lint-baseline.xml +++ b/common/lint-baseline.xml @@ -1,5 +1,5 @@ - + @@ -19,7 +19,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -30,7 +30,7 @@ errorLine2=" ^"> @@ -41,7 +41,7 @@ errorLine2=" ^"> @@ -52,7 +52,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -63,7 +63,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -74,7 +74,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -96,7 +96,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -107,76 +107,10 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wear/lint-baseline.xml b/wear/lint-baseline.xml index c8f14e50567..ee556116c3c 100644 --- a/wear/lint-baseline.xml +++ b/wear/lint-baseline.xml @@ -1,5 +1,5 @@ - + From 30567e67c69340c9ab0c00f857e59cffacde038d Mon Sep 17 00:00:00 2001 From: Timothy <6560631+TimoPtr@users.noreply.github.com> Date: Wed, 27 May 2026 13:12:32 +0200 Subject: [PATCH 4/7] Migrate from SdkVersionProvider to SdkVersion and use an object --- .../android/common/util/SdkVersion.kt | 34 +++++++++++++++ .../android/common/util/SdkVersionProvider.kt | 41 ------------------- .../lint/sdkversion/SdkVersionDetector.kt | 18 ++++---- .../lint/sdkversion/SdkVersionDetectorTest.kt | 2 +- 4 files changed, 44 insertions(+), 51 deletions(-) create mode 100644 common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersion.kt delete mode 100644 common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersion.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersion.kt new file mode 100644 index 00000000000..8c1a2312dc2 --- /dev/null +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersion.kt @@ -0,0 +1,34 @@ +package io.homeassistant.companion.android.common.util + +import android.annotation.SuppressLint +import android.os.Build +import androidx.annotation.ChecksSdkIntAtLeast +import androidx.annotation.VisibleForTesting + +/** + * Reports whether the current Android SDK level is at least a given version, backed by the real + * device's [Build.VERSION.SDK_INT]. This is the single intentional raw read of `SDK_INT` in + * production code, so the `SdkVersionAccess` Lint rule is explicitly suppressed. + * + * The [ChecksSdkIntAtLeast] annotation tells Android Lint that calls to [isAtLeast] are valid + * SDK version gates, so callers can reference newer-API symbols below the check without needing + * `@SuppressLint("NewApi")`. + * + * The [sdkInt] setter is [VisibleForTesting] only: tests that need to simulate a different SDK + * level can assign it. + */ +@SuppressLint("SdkVersionAccess") +object SdkVersion { + var sdkInt = Build.VERSION.SDK_INT + @VisibleForTesting set + + @ChecksSdkIntAtLeast(parameter = 0) + fun isAtLeast(version: Int): Boolean { + return sdkInt >= version + } + + /** Returns the device's [sdkInt] as a string, for use in diagnostic logging and registration payloads. */ + override fun toString(): String { + return sdkInt.toString() + } +} diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt deleted file mode 100644 index bd11835f0fa..00000000000 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersionProvider.kt +++ /dev/null @@ -1,41 +0,0 @@ -package io.homeassistant.companion.android.common.util - -import android.annotation.SuppressLint -import android.os.Build -import androidx.annotation.ChecksSdkIntAtLeast -import androidx.annotation.VisibleForTesting - -/** - * Reports whether the current Android SDK level is at least [api]. Tests can substitute a fake - * provider to simulate a SDK version. - * - * The [ChecksSdkIntAtLeast] annotation tells Android Lint that calls to [isAtLeast] are valid - * SDK version gates, so callers can reference newer-API symbols below the check without needing - * `@SuppressLint("NewApi")`. - */ -fun interface SdkVersionProvider { - @ChecksSdkIntAtLeast(parameter = 0) - fun isAtLeast(api: Int): Boolean -} - -/** - * Default [SdkVersionProvider] backed by the real device's [Build.VERSION.SDK_INT]. This is the - * single intentional raw read of `SDK_INT` in production code, so the `SdkVersionAccess` Lint - * rule is explicitly suppressed. - * - * The setter is [VisibleForTesting] only: tests that need to simulate a different SDK level - * can assign a fake here and restore the original in `@AfterEach`. - */ -@SuppressLint("SdkVersionAccess") -var sdkVersion: SdkVersionProvider = object : SdkVersionProvider { - @ChecksSdkIntAtLeast(parameter = 0) - override fun isAtLeast(api: Int): Boolean { - return Build.VERSION.SDK_INT >= api - } - - /** Returns the device's `SDK_INT` as a string, for use in diagnostic logging and registration payloads. */ - override fun toString(): String { - return Build.VERSION.SDK_INT.toString() - } -} - @VisibleForTesting set diff --git a/lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt b/lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt index 03876c7c196..ee260174330 100644 --- a/lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt +++ b/lint/src/main/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetector.kt @@ -20,20 +20,20 @@ object SdkVersionDetector { @JvmField val ISSUE = Issue.create( id = "SdkVersionAccess", - briefDescription = "Direct read of Build.VERSION.SDK_INT bypasses the sdkVersion provider", + briefDescription = "Direct read of Build.VERSION.SDK_INT bypasses the SdkVersion object", explanation = """ - Production code should call `sdkVersion.isAtLeast(api)` instead of reading - `Build.VERSION.SDK_INT` directly for version gates. The provider has a - `@VisibleForTesting` setter so tests can simulate other SDK levels, and its + Code should call `SdkVersion.isAtLeast(version)` instead of reading + `Build.VERSION.SDK_INT` directly for version gates. `SdkVersion` exposes a + `@VisibleForTesting` `sdkInt` property so tests can simulate other SDK levels, and its `@ChecksSdkIntAtLeast(parameter = 0)` annotation lets Android Lint recognise the version gate without `@SuppressLint("NewApi")`. When you need the raw `SDK_INT` value as a string — typically for diagnostic - logging or registration payloads — use `sdkVersion.toString()` (or string - interpolation `"... ${"$"}sdkVersion ..."`) instead of `Build.VERSION.SDK_INT.toString()`. + logging or registration payloads — use `SdkVersion.toString()` (or string + interpolation `"... ${"$"}SdkVersion ..."`) instead of `Build.VERSION.SDK_INT.toString()`. If a call site genuinely needs to read `Build.VERSION.SDK_INT` directly (typically - the single declaration of `sdkVersion` itself), suppress with + the `SdkVersion` object itself), suppress with `@SuppressLint("SdkVersionAccess")` on the enclosing function, property, or class and document why in code review. """.trimIndent(), @@ -61,8 +61,8 @@ object SdkVersionDetector { ISSUE, reference, context.getLocation(reference), - "Read of `Build.VERSION.SDK_INT` is forbidden. Use `sdkVersion.isAtLeast(api)` " + - "for version gates, or `sdkVersion.toString()` / `\"... \$sdkVersion ...\"` " + + "Read of `Build.VERSION.SDK_INT` is forbidden. Use `SdkVersion.isAtLeast(version)` " + + "for version gates, or `SdkVersion.toString()` / `\"... \$SdkVersion ...\"` " + "when you need the raw value as a string. Suppress with " + "`@SuppressLint(\"SdkVersionAccess\")` only if this site is one of the few " + "legitimate raw accesses.", diff --git a/lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt b/lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt index 736228f93c0..d20f8af41ec 100644 --- a/lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt +++ b/lint/src/test/kotlin/io/homeassistant/lint/sdkversion/SdkVersionDetectorTest.kt @@ -39,7 +39,7 @@ class SdkVersionDetectorTest { .run() .expect( """ - src/com/example/test.kt:5: Error: Read of Build.VERSION.SDK_INT is forbidden. Use sdkVersion.isAtLeast(api) for version gates, or sdkVersion.toString() / "... ${"$"}sdkVersion ..." when you need the raw value as a string. Suppress with @SuppressLint("SdkVersionAccess") only if this site is one of the few legitimate raw accesses. [SdkVersionAccess] + src/com/example/test.kt:5: Error: Read of Build.VERSION.SDK_INT is forbidden. Use SdkVersion.isAtLeast(version) for version gates, or SdkVersion.toString() / "... ${"$"}SdkVersion ..." when you need the raw value as a string. Suppress with @SuppressLint("SdkVersionAccess") only if this site is one of the few legitimate raw accesses. [SdkVersionAccess] fun checkSdk(): Boolean = Build.VERSION.SDK_INT >= 30 ~~~~~~~ 1 error From ed3c142bf0f46e6263be832cfae2a83de097a3f5 Mon Sep 17 00:00:00 2001 From: Timothy <6560631+TimoPtr@users.noreply.github.com> Date: Wed, 27 May 2026 13:13:06 +0200 Subject: [PATCH 5/7] Update all usages to adjust to the new name --- .../developer/DemoExoPlayerActivity.kt | 4 ++-- .../location/HighAccuracyLocationService.kt | 6 ++--- .../android/matter/MatterManagerImpl.kt | 4 ++-- .../android/sensors/ActivitySensorManager.kt | 4 ++-- .../sensors/AndroidAutoSensorManager.kt | 6 ++--- .../android/sensors/LocationSensorManager.kt | 10 ++++----- .../android/thread/ThreadManagerImpl.kt | 4 ++-- .../android/HomeAssistantApplication.kt | 12 +++++----- .../android/assist/AssistActivity.kt | 6 ++--- .../service/AssistRecognitionService.kt | 4 ++-- .../service/AssistVoiceInteractionService.kt | 8 +++---- .../companion/android/controls/HaControl.kt | 4 ++-- .../controls/HaControlsProviderService.kt | 8 +++---- .../haptic/HapticFeedbackPerformer.kt | 10 ++++----- .../frontend/permissions/PermissionManager.kt | 9 ++++---- .../android/improv/ImprovRepositoryImpl.kt | 4 ++-- .../android/improv/ui/ImprovSheetView.kt | 4 ++-- .../android/launch/LaunchActivity.kt | 4 ++-- .../android/notifications/MessagingManager.kt | 22 +++++++++---------- .../serverdiscovery/HomeAssistantSearcher.kt | 4 ++-- .../serverdiscovery/ServerDiscoveryScreen.kt | 4 ++-- .../companion/android/qs/TileExtensions.kt | 10 ++++----- .../android/qs/TilePreferenceActivity.kt | 4 ++-- .../android/sensors/CarSensorManager.kt | 4 ++-- .../android/sensors/GeocodeSensorManager.kt | 6 ++--- .../android/sensors/LastAppSensorManager.kt | 4 ++-- .../sensors/NotificationSensorManager.kt | 8 +++---- .../android/settings/SettingsFragment.kt | 22 +++++++++---------- .../android/settings/SettingsPresenterImpl.kt | 4 ++-- .../assist/DefaultAssistantManager.kt | 4 ++-- .../controls/ManageControlsViewModel.kt | 6 ++--- .../controls/views/ManageControlsView.kt | 6 ++--- .../settings/language/LanguagesManager.kt | 10 ++++----- .../android/settings/log/LogFragment.kt | 6 ++--- .../settings/qs/ManageTilesViewModel.kt | 6 ++--- .../settings/qs/views/ManageTilesView.kt | 4 ++-- .../settings/sensor/SensorDetailFragment.kt | 6 ++--- .../settings/sensor/SensorDetailViewModel.kt | 8 +++---- .../sensor/views/SensorUpdateFrequencyView.kt | 4 ++-- .../shortcuts/ManageShortcutsViewModel.kt | 8 +++---- .../android/settings/ssid/SsidFragment.kt | 12 +++++----- .../android/settings/ssid/views/SsidView.kt | 4 ++-- .../websocket/views/WebsocketSettingView.kt | 4 ++-- .../widgets/ManageWidgetsViewModel.kt | 4 ++-- .../android/themes/NightModeManager.kt | 4 ++-- .../android/util/ContextExtensions.kt | 4 ++-- .../android/util/DataUriDownloadManager.kt | 6 ++--- .../util/compose/LocationPermissionState.kt | 8 +++---- .../android/util/compose/webview/HAWebView.kt | 4 ++-- .../android/util/vehicle/NativeMode.kt | 4 ++-- .../android/util/vehicle/SettingsAction.kt | 4 ++-- .../android/websocket/WebsocketManager.kt | 8 +++---- .../android/webview/WebViewActivity.kt | 12 +++++----- .../android/webview/WebViewContentScreen.kt | 4 ++-- .../button/ButtonWidgetConfigureActivity.kt | 4 ++-- .../camera/CameraWidgetConfigureActivity.kt | 4 ++-- .../entity/EntityWidgetConfigureActivity.kt | 4 ++-- ...iaPlayerControlsWidgetConfigureActivity.kt | 4 ++-- .../TemplateWidgetConfigureActivity.kt | 4 ++-- .../todo/TodoWidgetConfigureActivity.kt | 4 ++-- .../android/widgets/todo/TodoWidgetState.kt | 4 ++-- .../android/location/LocationProvider.kt | 4 ++-- .../permissions/PermissionManagerTest.kt | 7 +++--- .../common/bluetooth/ble/MonitoringManager.kt | 4 ++-- .../compose/util/PainterResourceUtil.kt | 4 ++-- .../android/common/data/integration/Entity.kt | 4 ++-- .../common/data/network/WifiHelperImpl.kt | 4 ++-- .../NotificationDeleteReceiver.kt | 4 ++-- .../notifications/NotificationFunctions.kt | 8 +++---- .../common/sensors/AppSensorManagerBase.kt | 6 ++--- .../common/sensors/AudioSensorManager.kt | 12 +++++----- .../common/sensors/BatterySensorManager.kt | 12 +++++----- .../common/sensors/BluetoothSensorManager.kt | 12 +++++----- .../common/sensors/MobileDataManager.kt | 8 +++---- .../common/sensors/NetworkSensorManager.kt | 8 +++---- .../common/sensors/PhoneStateSensorManager.kt | 12 +++++----- .../android/common/sensors/SensorManager.kt | 6 ++--- .../common/sensors/SensorReceiverBase.kt | 4 ++-- .../common/sensors/SensorWorkerBase.kt | 6 ++--- .../common/sensors/StepsSensorManager.kt | 4 ++-- .../common/util/DisabledLocationHandler.kt | 4 ++-- .../android/common/util/ExoPlayerExt.kt | 2 +- .../util/NotificationManagerExtensions.kt | 2 +- .../android/database/migration/Utils.kt | 4 ++-- .../companion/android/di/DataModule.kt | 4 ++-- .../android/HomeAssistantApplication.kt | 10 ++++----- .../companion/android/home/HomeActivity.kt | 4 ++-- .../companion/android/home/views/SensorUi.kt | 6 ++--- .../sensors/BedtimeModeSensorManager.kt | 4 ++-- .../sensors/HealthServicesSensorManager.kt | 4 ++-- .../android/sensors/HeartRateSensorManager.kt | 4 ++-- .../companion/android/tiles/TileViews.kt | 4 ++-- 92 files changed, 280 insertions(+), 282 deletions(-) diff --git a/app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt b/app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt index 36918ddf333..6d23302b494 100644 --- a/app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt +++ b/app/src/debug/kotlin/io/homeassistant/companion/android/developer/DemoExoPlayerActivity.kt @@ -31,8 +31,8 @@ import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.datasource.DataSource import dagger.hilt.android.AndroidEntryPoint +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.initializePlayer -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme import io.homeassistant.companion.android.util.compose.media.player.HAMediaPlayer import javax.inject.Inject @@ -99,7 +99,7 @@ private fun HAMediaPlayer( player = null } - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { // Initialize/release in onStart()/onStop() only because in a multi-window environment multiple // apps can be visible at the same time. The apps that are out-of-focus are paused, but video // playback should continue. diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt b/app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt index 67c5aa01778..b64d28282b9 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/location/HighAccuracyLocationService.kt @@ -22,7 +22,7 @@ import com.google.android.gms.location.Priority import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.CHANNEL_HIGH_ACCURACY import io.homeassistant.companion.android.common.util.FailFast -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.sensors.LocationSensorManager import io.homeassistant.companion.android.util.ForegroundServiceLauncher import kotlin.math.abs @@ -112,7 +112,7 @@ class HighAccuracyLocationService : Service() { } private fun createNotificationBuilder(context: Context) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val channel = NotificationChannel( CHANNEL_HIGH_ACCURACY, @@ -154,7 +154,7 @@ class HighAccuracyLocationService : Service() { createNotificationBuilder(this) notification = notificationBuilder.build() - val type = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) FOREGROUND_SERVICE_TYPE_LOCATION else 0 + val type = if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) FOREGROUND_SERVICE_TYPE_LOCATION else 0 FailFast.failOnCatch { // Sometimes the service cannot be started as foreground due to the app being in a state where // this is not allowed. We haven't identified how to avoid starting the service in this state yet. diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt b/app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt index 80a556473f3..f200478ab38 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/matter/MatterManagerImpl.kt @@ -9,8 +9,8 @@ import com.google.android.gms.home.matter.Matter import com.google.android.gms.home.matter.commissioning.CommissioningRequest import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.MatterCommissionResponse +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject import kotlinx.coroutines.CancellationException import timber.log.Timber @@ -20,7 +20,7 @@ class MatterManagerImpl @Inject constructor( private val packageManager: PackageManager, ) : MatterManager { - override fun appSupportsCommissioning(): Boolean = sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) && + override fun appSupportsCommissioning(): Boolean = SdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) && !packageManager.isAutomotive() override suspend fun coreSupportsCommissioning(serverId: Int): Boolean { diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt index f130e850ef4..19eff5dd537 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/ActivitySensorManager.kt @@ -17,8 +17,8 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.sensors.SensorReceiverBase import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import java.util.concurrent.TimeUnit import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -212,7 +212,7 @@ class ActivitySensorManager : } override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf( Manifest.permission.ACTIVITY_RECOGNITION, ) diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt index cd70a267f86..02ef9b6fea0 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/AndroidAutoSensorManager.kt @@ -6,7 +6,7 @@ import androidx.car.app.connection.CarConnection import androidx.lifecycle.Observer import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import kotlinx.coroutines.launch import timber.log.Timber @@ -30,7 +30,7 @@ class AndroidAutoSensorManager : get() = commonR.string.sensor_name_android_auto override suspend fun getAvailableSensors(context: Context): List { - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { listOf(androidAutoConnected) } else { emptyList() @@ -38,7 +38,7 @@ class AndroidAutoSensorManager : } override fun hasSensor(context: Context): Boolean { - return sdkVersion.isAtLeast(Build.VERSION_CODES.O) + return SdkVersion.isAtLeast(Build.VERSION_CODES.O) } override fun requiredPermissions(context: Context, sensorId: String): Array { diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt index bd4759f68b5..1261afc1d39 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/sensors/LocationSensorManager.kt @@ -36,7 +36,7 @@ import io.homeassistant.companion.android.common.notifications.DeviceCommandData import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.sensors.SensorReceiverBase import io.homeassistant.companion.android.common.util.DisabledLocationHandler -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.DatabaseEntryPoint import io.homeassistant.companion.android.database.location.LocationHistoryDao import io.homeassistant.companion.android.database.location.LocationHistoryItem @@ -862,7 +862,7 @@ class LocationSensorManager : "provider" to geofencingEvent.triggeringLocation!!.provider, "time" to geofencingEvent.triggeringLocation!!.time, "vertical_accuracy" to - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { geofencingEvent.triggeringLocation!!.verticalAccuracyMeters.toInt() } else { 0 @@ -975,7 +975,7 @@ class LocationSensorManager : speed = location.speed.toInt(), altitude = location.altitude.toInt(), course = location.bearing.toInt(), - verticalAccuracy = if (sdkVersion.isAtLeast( + verticalAccuracy = if (SdkVersion.isAtLeast( Build.VERSION_CODES.O, ) ) { @@ -1368,7 +1368,7 @@ class LocationSensorManager : override fun requiredPermissions(context: Context, sensorId: String): Array { return when { - (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { + (SdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, @@ -1378,7 +1378,7 @@ class LocationSensorManager : ) } - (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) -> { + (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) -> { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, diff --git a/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt b/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt index 8954108f052..b9a46d714b1 100644 --- a/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt +++ b/app/src/full/kotlin/io/homeassistant/companion/android/thread/ThreadManagerImpl.kt @@ -15,8 +15,8 @@ import com.google.android.gms.threadnetwork.ThreadNetworkStatusCodes import io.homeassistant.companion.android.common.data.HomeAssistantVersion import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.ThreadDatasetResponse +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException @@ -34,7 +34,7 @@ class ThreadManagerImpl @Inject constructor( private const val BORDER_AGENT_ID = "0000000000000001" } - override fun appSupportsThread(): Boolean = sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) && + override fun appSupportsThread(): Boolean = SdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) && !packageManager.isAutomotive() override suspend fun coreSupportsThread(serverId: Int): Boolean { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt b/app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt index f5c5145ac40..f1e1027affd 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt @@ -24,9 +24,9 @@ import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.sensors.AudioSensorManager import io.homeassistant.companion.android.common.sensors.LastUpdateManager import io.homeassistant.companion.android.common.util.HAStrictMode +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.configureComposeDiagnosticStackTrace import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.SensorDao import io.homeassistant.companion.android.database.settings.SensorUpdateFrequencySetting import io.homeassistant.companion.android.database.settings.SettingsDao @@ -87,7 +87,7 @@ open class HomeAssistantApplication : Timber.plant(Timber.DebugTree()) super.onCreate() - if (sdkVersion.isAtLeast(Build.VERSION_CODES.S) && + if (SdkVersion.isAtLeast(Build.VERSION_CODES.S) && BuildConfig.DEBUG && !BuildConfig.NO_STRICT_MODE ) { @@ -97,7 +97,7 @@ open class HomeAssistantApplication : ) } - Timber.i("Running ${BuildConfig.VERSION_NAME} on SDK $sdkVersion") + Timber.i("Running ${BuildConfig.VERSION_NAME} on SDK $SdkVersion") registerActivityLifecycleCallbacks(LifecycleHandler) @@ -240,7 +240,7 @@ open class HomeAssistantApplication : ) // Listen for microphone mute changes - if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { ContextCompat.registerReceiver( this, sensorReceiver, @@ -250,7 +250,7 @@ open class HomeAssistantApplication : } // Listen for speakerphone state changes - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { ContextCompat.registerReceiver( this, sensorReceiver, @@ -305,7 +305,7 @@ open class HomeAssistantApplication : } // Register for changes to the managed profile availability - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { ContextCompat.registerReceiver( this, sensorReceiver, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt index be7fa30bcef..f62f6480bbb 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/assist/AssistActivity.kt @@ -21,7 +21,7 @@ import io.homeassistant.companion.android.assist.service.AssistVoiceInteractionS import io.homeassistant.companion.android.assist.ui.AssistSheetView import io.homeassistant.companion.android.common.assist.AssistViewModelBase import io.homeassistant.companion.android.common.data.servers.ServerManager -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.launch.LaunchActivity import io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme import io.homeassistant.companion.android.webview.WebViewActivity @@ -193,7 +193,7 @@ class AssistActivity : BaseActivity() { contextIsLocked = locked if (locked) { window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1)) { + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1)) { @Suppress("DEPRECATION") window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) } else { @@ -201,7 +201,7 @@ class AssistActivity : BaseActivity() { setTurnScreenOn(true) } } else { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1)) { + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1)) { @Suppress("DEPRECATION") window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) } else { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt b/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt index e90815f1da6..f23c13f4763 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistRecognitionService.kt @@ -4,7 +4,7 @@ import android.content.Intent import android.os.Build import android.speech.RecognitionService import android.speech.SpeechRecognizer -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import timber.log.Timber /** @@ -22,7 +22,7 @@ class AssistRecognitionService : RecognitionService() { } override fun onCheckRecognitionSupport(recognizerIntent: Intent, supportCallback: SupportCallback) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { supportCallback.onError(SpeechRecognizer.ERROR_CLIENT) } } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt b/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt index a158c87b9c9..08ad5335741 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/assist/service/AssistVoiceInteractionService.kt @@ -26,7 +26,7 @@ import io.homeassistant.companion.android.assist.wakeword.WakeWordListener import io.homeassistant.companion.android.assist.wakeword.WakeWordListenerFactory import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.CHANNEL_ASSIST_LISTENING -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.settings.assist.AssistConfigManager import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -223,7 +223,7 @@ class AssistVoiceInteractionService : VoiceInteractionService() { PackageManager.PERMISSION_GRANTED private fun startForegroundWithNotification(model: MicroWakeWordModelConfig) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { startForeground( NOTIFICATION_ID, createNotification(model), @@ -235,7 +235,7 @@ class AssistVoiceInteractionService : VoiceInteractionService() { } private fun stopForegroundCompat() { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { stopForeground(STOP_FOREGROUND_REMOVE) } else { @Suppress("DEPRECATION") @@ -282,7 +282,7 @@ class AssistVoiceInteractionService : VoiceInteractionService() { } private fun createNotificationChannel() { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val channel = NotificationChannel( CHANNEL_ASSIST_LISTENING, getString(commonR.string.assist_listening_channel), diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt b/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt index 12d02a2e470..ff01ef6f11a 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControl.kt @@ -21,7 +21,7 @@ import io.homeassistant.companion.android.common.data.integration.IntegrationRep import io.homeassistant.companion.android.common.data.integration.friendlyState import io.homeassistant.companion.android.common.data.integration.getIcon import io.homeassistant.companion.android.common.data.integration.isActive -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.webview.WebViewActivity @RequiresApi(Build.VERSION_CODES.R) @@ -58,7 +58,7 @@ interface HaControl { } control.setStatus(Control.STATUS_OK) control.setStatusText(entity.friendlyState(context)) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { control.setAuthRequired(info.authRequired) } if (entity.attributes["icon"]?.toString()?.startsWith("mdi:") == true && diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt b/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt index 943559e2ca9..878467bef4e 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/controls/HaControlsProviderService.kt @@ -18,7 +18,7 @@ import io.homeassistant.companion.android.common.data.servers.firstUrlOrNull import io.homeassistant.companion.android.common.data.websocket.impl.entities.AreaRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.DeviceRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.util.RegistriesDataHandler import java.time.LocalDateTime import java.util.concurrent.Flow @@ -73,7 +73,7 @@ class HaControlsProviderService : ControlsProviderService() { .map { it.key } .filter { domainToMinimumApi[it] == null || - sdkVersion.isAtLeast(domainToMinimumApi[it]!!) + SdkVersion.isAtLeast(domainToMinimumApi[it]!!) } } @@ -150,7 +150,7 @@ class HaControlsProviderService : ControlsProviderService() { allEntities .filter { domainToMinimumApi[it.second.domain] == null || - sdkVersion.isAtLeast(domainToMinimumApi[it.second.domain]!!) + SdkVersion.isAtLeast(domainToMinimumApi[it.second.domain]!!) } .mapNotNull { (serverId, entity) -> try { @@ -556,7 +556,7 @@ class HaControlsProviderService : ControlsProviderService() { ) private suspend fun entityRequiresAuth(entityId: String, serverId: Int): Boolean { - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { val setting = prefsRepository.getControlsAuthRequired() if (setting == ControlsAuthRequiredSetting.SELECTION) { val includeList = prefsRepository.getControlsAuthEntities() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt b/app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt index 0203149b231..f3e02a648f1 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/frontend/haptic/HapticFeedbackPerformer.kt @@ -6,7 +6,7 @@ import android.os.Vibrator import android.view.HapticFeedbackConstants import android.view.View import androidx.core.content.getSystemService -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.frontend.externalbus.incoming.HapticType import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -49,7 +49,7 @@ object HapticFeedbackPerformer { } private fun performSuccess(view: View) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.R)) { view.performHapticFeedback(HapticFeedbackConstants.CONFIRM) } else { vibrate(view, duration = SUCCESS_FALLBACK_DURATION) @@ -57,7 +57,7 @@ object HapticFeedbackPerformer { } private fun performWarning(view: View) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { view.context.getSystemService()?.vibrate( VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK), ) @@ -67,7 +67,7 @@ object HapticFeedbackPerformer { } private fun performFailure(view: View) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.R)) { view.performHapticFeedback(HapticFeedbackConstants.REJECT) } else { vibrate(view, duration = FAILURE_FALLBACK_DURATION) @@ -75,7 +75,7 @@ object HapticFeedbackPerformer { } private fun performSelection(view: View) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.R)) { view.performHapticFeedback(HapticFeedbackConstants.GESTURE_START) } else { vibrate(view, duration = SELECTION_FALLBACK_DURATION) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt index fc401485094..a5f9b307334 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/frontend/permissions/PermissionManager.kt @@ -6,8 +6,8 @@ import android.webkit.PermissionRequest as WebViewPermissionRequest import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.NotificationStatusProvider import io.homeassistant.companion.android.common.util.PermissionChecker +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.SingleSlotQueue -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.settings.SensorUpdateFrequencySetting import io.homeassistant.companion.android.database.settings.Setting import io.homeassistant.companion.android.database.settings.SettingsDao @@ -44,7 +44,6 @@ internal class PermissionManager @Inject constructor( @FcmSupport private val fcmSupport: Boolean, private val notificationStatusProvider: NotificationStatusProvider, private val permissionChecker: PermissionChecker, - // Need for testing to avoid the need of Robolectric ) { private val queue = SingleSlotQueue() @@ -69,7 +68,7 @@ internal class PermissionManager @Inject constructor( * @param serverId The server to check notification preferences for */ suspend fun checkNotificationPermission(serverId: Int) { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) return + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) return if (!shouldAskNotificationPermission(serverId)) return val granted: Boolean? = queue.awaitResult { resolve -> @@ -97,7 +96,7 @@ internal class PermissionManager @Inject constructor( * user declined the permission */ suspend fun checkLocalNetworkPermission(): Boolean { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return true + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return true if (permissionChecker.hasPermission(Manifest.permission.ACCESS_LOCAL_NETWORK)) return true Timber.d("Local network permission required, awaiting user response") @@ -118,7 +117,7 @@ internal class PermissionManager @Inject constructor( * the user declined the permission */ suspend fun checkStoragePermissionForDownload(): Boolean { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) return true + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) return true if (permissionChecker.hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) return true Timber.d("Storage permission required for download, awaiting user response") diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt b/app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt index 42094a0dc46..7525f90425d 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/improv/ImprovRepositoryImpl.kt @@ -10,7 +10,7 @@ import com.wifi.improv.ErrorState import com.wifi.improv.ImprovDevice import com.wifi.improv.ImprovManager import com.wifi.improv.ImprovManagerCallback -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -40,7 +40,7 @@ class ImprovRepositoryImpl @Inject constructor() : override fun getRequiredPermissions(): Array { var required = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.S)) { required += Manifest.permission.BLUETOOTH_SCAN required += Manifest.permission.BLUETOOTH_CONNECT } else { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt index 7cc5d1f21fb..e72954b879f 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/improv/ui/ImprovSheetView.kt @@ -50,7 +50,7 @@ import com.wifi.improv.DeviceState import com.wifi.improv.ErrorState import com.wifi.improv.ImprovDevice import io.homeassistant.companion.android.common.R as commonR -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.util.compose.ModalBottomSheet @Composable @@ -95,7 +95,7 @@ fun ImprovSheetView( ImprovWifiInput( activeSsid = if (screenState.activeSsid?.isNotBlank() == true && ( - !sdkVersion.isAtLeast(Build.VERSION_CODES.R) || + !SdkVersion.isAtLeast(Build.VERSION_CODES.R) || screenState.activeSsid !== WifiManager.UNKNOWN_SSID ) ) { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt index e8b73b36ffe..a280260b7a3 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt @@ -40,7 +40,7 @@ import io.homeassistant.companion.android.authenticator.Authenticator import io.homeassistant.companion.android.authenticator.Authenticator.Companion.AuthenticationResult import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.compose.theme.HATheme -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.launch.applock.HazeLockOverlay import io.homeassistant.companion.android.sensors.SensorReceiver import io.homeassistant.companion.android.sensors.SensorWorker @@ -247,7 +247,7 @@ class LaunchActivity : AppCompatActivity() { if (WIPFeature.USE_FRONTEND_V2) { viewModel.onAppPaused() - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O)) return + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.O)) return if (!packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) return val readiness = viewModel.pipReadiness.value ?: return val params = PictureInPictureParams.Builder() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt index 92f3f0960e4..9c01ddd9122 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/notifications/MessagingManager.kt @@ -66,11 +66,11 @@ import io.homeassistant.companion.android.common.notifications.handleText import io.homeassistant.companion.android.common.notifications.parseColor import io.homeassistant.companion.android.common.notifications.parseVibrationPattern import io.homeassistant.companion.android.common.notifications.prepareText +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.cancelGroupIfNeeded import io.homeassistant.companion.android.common.util.getActiveNotification import io.homeassistant.companion.android.common.util.isAutomotive import io.homeassistant.companion.android.common.util.kotlinJsonMapper -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.common.util.toJsonObject import io.homeassistant.companion.android.common.util.tts.TextToSpeechClient import io.homeassistant.companion.android.common.util.tts.TextToSpeechData @@ -421,7 +421,7 @@ class MessagingManager @Inject constructor( if ( !jsonData[NotificationData.COMMAND].isNullOrEmpty() && jsonData[NotificationData.COMMAND] in DeviceCommandData.ENABLE_COMMANDS && - !sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) + !SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) ) { handleDeviceCommands(jsonData) } else { @@ -637,7 +637,7 @@ class MessagingManager @Inject constructor( val channelID: String = createChannelID(channelName) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O) && channelID != NotificationChannel.DEFAULT_CHANNEL_ID) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O) && channelID != NotificationChannel.DEFAULT_CHANNEL_ID) { notificationManagerCompat.deleteNotificationChannel(channelID) } } @@ -730,7 +730,7 @@ class MessagingManager @Inject constructor( COMMAND_BLUETOOTH -> { val bluetoothAdapter = context.getSystemService()?.adapter - if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.S)) { when (PackageManager.PERMISSION_GRANTED) { ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) -> { Timber.d("We have proper bluetooth permissions proceeding with command") @@ -1022,7 +1022,7 @@ class MessagingManager @Inject constructor( group = NotificationData.GROUP_PREFIX + group groupId = group.hashCode() } else { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { val notification = notificationManagerCompat.getActiveNotification(tag, messageId) if (notification != null && notification.isGroup) { previousGroup = NotificationData.GROUP_PREFIX + notification.tag @@ -1079,7 +1079,7 @@ class MessagingManager @Inject constructor( val useCarNotification = handleCarUiVisible(context, notificationBuilder, data) - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { handleLegacyPriority(notificationBuilder, data) handleLegacyLedColor(notificationBuilder, data) handleLegacyVibrationPattern(notificationBuilder, data) @@ -1125,7 +1125,7 @@ class MessagingManager @Inject constructor( builder.setWhen(notificationWhen) builder.setUsesChronometer(usesChronometer) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { val countdown = notificationWhen > System.currentTimeMillis() // Without this builder.setChronometerCountDown throws a null reference exception builder.addExtras(Bundle()) @@ -1152,7 +1152,7 @@ class MessagingManager @Inject constructor( } private fun handleLive(builder: NotificationCompat.Builder, data: Map) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.BAKLAVA)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.BAKLAVA)) { val liveUpdate = data[LIVE_UPDATE]?.toBoolean() ?: false val criticalText = data[CRITICAL_TEXT] @@ -1172,7 +1172,7 @@ class MessagingManager @Inject constructor( builder: NotificationCompat.Builder, data: Map, ): Boolean { - if (data[CAR_UI]?.toBoolean() == true && sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (data[CAR_UI]?.toBoolean() == true && SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val carExtender = CarAppExtender.Builder() if (context.isAutomotive() || BuildConfig.FLAVOR == "full") { val carIntent = Intent(Intent.ACTION_VIEW).apply { @@ -1342,7 +1342,7 @@ class MessagingManager @Inject constructor( .setLargeIcon(bitmap) .setStyle( NotificationCompat.BigPictureStyle().also { style -> - if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { saveTempAnimatedImage( serverId, url, @@ -1741,7 +1741,7 @@ class MessagingManager @Inject constructor( } private fun handleReplyHistory(builder: NotificationCompat.Builder, data: Map) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { val replies = data.entries .filter { it.key.startsWith(SOURCE_REPLY_HISTORY) } .sortedBy { it.key.substringAfter(SOURCE_REPLY_HISTORY).toInt() } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt b/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt index 15da55ee5a6..b4cffa2821c 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcher.kt @@ -7,7 +7,7 @@ import android.os.Build import androidx.annotation.VisibleForTesting import io.homeassistant.companion.android.common.data.HomeAssistantVersion import io.homeassistant.companion.android.common.util.FailFast -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import java.net.MalformedURLException import java.net.URL import java.util.concurrent.atomic.AtomicBoolean @@ -158,7 +158,7 @@ internal class HomeAssistantSearcherImpl @Inject constructor( nsdManager.resolveService(serviceInfo, listener) awaitClose { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { try { nsdManager.stopServiceResolution(listener) } catch (e: IllegalArgumentException) { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt b/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt index eb658a0166f..9bce6b6b9a5 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/ServerDiscoveryScreen.kt @@ -90,7 +90,7 @@ import io.homeassistant.companion.android.common.compose.theme.HAThemeForPreview import io.homeassistant.companion.android.common.compose.theme.LocalHAColorScheme import io.homeassistant.companion.android.common.compose.theme.MaxButtonWidth import io.homeassistant.companion.android.common.data.HomeAssistantVersion -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.util.compose.HAPreviews import java.net.URL import kotlinx.coroutines.launch @@ -144,7 +144,7 @@ internal fun ServerDiscoveryScreen( @OptIn(ExperimentalPermissionsApi::class) @Composable private fun rememberLocalNetworkPermissionGranted(onDenied: () -> Unit): Boolean { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return true + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return true val permissionState = rememberPermissionState(Manifest.permission.ACCESS_LOCAL_NETWORK) { granted -> if (!granted) onDenied() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt b/app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt index f5eddfb6f7c..6141506e051 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/qs/TileExtensions.kt @@ -30,7 +30,7 @@ import io.homeassistant.companion.android.common.data.integration.getIcon import io.homeassistant.companion.android.common.data.integration.isActive import io.homeassistant.companion.android.common.data.integration.onEntityPressedWithoutState import io.homeassistant.companion.android.common.data.servers.ServerManager -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.qs.TileDao import io.homeassistant.companion.android.database.qs.TileEntity import io.homeassistant.companion.android.database.qs.getHighestInUse @@ -147,7 +147,7 @@ abstract class TileExtensions : TileService() { try { return if (tileData != null && tileData.isSetup) { tile.label = tileData.label - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { tile.subtitle = tileData.subtitle } val state: Entity? = @@ -194,7 +194,7 @@ abstract class TileExtensions : TileService() { } else { Tile.STATE_UNAVAILABLE } - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { tile.subtitle = getString(commonR.string.tile_not_setup) } tile.updateTile() @@ -213,7 +213,7 @@ abstract class TileExtensions : TileService() { val vm = getSystemService() if (!isUnlock) { if (tileData?.shouldVibrate == true) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { vm?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) } else { @Suppress("DEPRECATION") @@ -282,7 +282,7 @@ abstract class TileExtensions : TileService() { if (e != null) Timber.e(e, "Unable to call service for tile ID: ${tileData?.id}") if (tileData != null && tileData.shouldVibrate) { val vm = getSystemService() - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { vm?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK)) } else { @Suppress("DEPRECATION") diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt index ad474838a70..f439ad747bc 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/qs/TilePreferenceActivity.kt @@ -9,7 +9,7 @@ import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.BaseActivity import io.homeassistant.companion.android.common.data.servers.ServerManager -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.qs.TileDao import io.homeassistant.companion.android.database.qs.isSetup import io.homeassistant.companion.android.launch.LaunchActivity @@ -35,7 +35,7 @@ class TilePreferenceActivity : BaseActivity() { super.onCreate(savedInstanceState) var tileId = "-1" - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { intent.extras?.let { extras -> BundleCompat.getParcelable( extras, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt index 94411a545a6..6b3d3ebe53d 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/CarSensorManager.kt @@ -16,8 +16,8 @@ import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.vehicle.HaCarAppService import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -218,7 +218,7 @@ class CarSensorManager : private lateinit var latestContext: Context - private val areCarSensorApisAvailable = sdkVersion.isAtLeast(Build.VERSION_CODES.O) + private val areCarSensorApisAvailable = SdkVersion.isAtLeast(Build.VERSION_CODES.O) private val isAutomotive get() = latestContext.isAutomotive() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt index e067630684c..119d8acb21c 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/GeocodeSensorManager.kt @@ -10,8 +10,8 @@ import androidx.annotation.VisibleForTesting import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.instant -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType import io.homeassistant.companion.android.location.HighAccuracyLocationService @@ -73,7 +73,7 @@ class GeocodeSensorManager : SensorManager { } override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, @@ -168,7 +168,7 @@ class GeocodeSensorManager : SensorManager { longitude: Double, maxResults: Int, ): List
{ - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { suspendCoroutine { cont -> getFromLocation( latitude, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt index 9f085283d40..5ea07ab4108 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/LastAppSensorManager.kt @@ -9,8 +9,8 @@ import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import timber.log.Timber class LastAppSensorManager : SensorManager { @@ -63,7 +63,7 @@ class LastAppSensorManager : SensorManager { try { val pm = context.packageManager - val appInfo = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + val appInfo = if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { pm.getApplicationInfo( lastApp, PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong()), diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt index 11bee0e03c3..dc3ba9b885c 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/sensors/NotificationSensorManager.kt @@ -18,8 +18,8 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.SensorSettingType import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -161,7 +161,7 @@ class NotificationSensorManager : put("group_id", sbn.notification.group) put("category", sbn.notification.category) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { put("channel_id", sbn.notification.channelId) } } @@ -224,7 +224,7 @@ class NotificationSensorManager : put("group_id", sbn.notification.group) put("category", sbn.notification.category) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { put("channel_id", sbn.notification.channelId) } } @@ -270,7 +270,7 @@ class NotificationSensorManager : put("${item.packageName}_${item.id}_group_id", item.notification.group) put("${item.packageName}_${item.id}_category", item.notification.category) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { put("${item.packageName}_${item.id}_channel_id", item.notification.channelId) } } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt index 223679464ed..17f144b5c8d 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsFragment.kt @@ -28,10 +28,10 @@ import io.homeassistant.companion.android.BuildConfig import io.homeassistant.companion.android.R import io.homeassistant.companion.android.authenticator.Authenticator.Companion.AuthenticationResult import io.homeassistant.companion.android.common.R as commonR +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive import io.homeassistant.companion.android.common.util.isIgnoringBatteryOptimizations import io.homeassistant.companion.android.common.util.maybeAskForIgnoringBatteryOptimizations -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.launch.intentLaunchOnboarding import io.homeassistant.companion.android.nfc.NfcSetupActivity @@ -209,7 +209,7 @@ class SettingsFragment( } if (!QuestUtil.isQuest) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N_MR1)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N_MR1)) { findPreference("shortcuts")?.let { it.isVisible = true } @@ -222,7 +222,7 @@ class SettingsFragment( } } - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { findPreference("quick_settings")?.let { it.isVisible = true } @@ -235,7 +235,7 @@ class SettingsFragment( } } - if (!isAutomotive && sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + if (!isAutomotive && SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { findPreference("device_controls")?.let { it.isVisible = true } @@ -255,7 +255,7 @@ class SettingsFragment( updateNotificationChannelPrefs() - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { findPreference("notification_permission")?.let { it.setOnPreferenceClickListener { openNotificationSettings() @@ -293,7 +293,7 @@ class SettingsFragment( if (rateLimits != null) { var formattedDate = rateLimits.resetsAt - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { try { val utcDateTime = Instant.parse(rateLimits.resetsAt) formattedDate = @@ -401,7 +401,7 @@ class SettingsFragment( findPreference("android_auto")?.let { it.isVisible = - sdkVersion.isAtLeast(Build.VERSION_CODES.O) && + SdkVersion.isAtLeast(Build.VERSION_CODES.O) && (BuildConfig.FLAVOR == "full" || isAutomotive) if (isAutomotive) { it.title = getString(commonR.string.android_automotive) @@ -434,7 +434,7 @@ class SettingsFragment( } private fun removeSystemFromThemesIfNeeded() { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { val pref = findPreference("themes") if (pref != null) { val systemIndex = pref.findIndexOfValue("system") @@ -530,7 +530,7 @@ class SettingsFragment( private fun updateNotificationChannelPrefs() { val notificationsEnabled = - !sdkVersion.isAtLeast(Build.VERSION_CODES.O) || + !SdkVersion.isAtLeast(Build.VERSION_CODES.O) || NotificationManagerCompat.from(requireContext()).areNotificationsEnabled() findPreference("notification_permission")?.let { @@ -540,7 +540,7 @@ class SettingsFragment( val uiManager = requireContext().getSystemService() it.isVisible = notificationsEnabled && - sdkVersion.isAtLeast(Build.VERSION_CODES.O) && + SdkVersion.isAtLeast(Build.VERSION_CODES.O) && uiManager?.currentModeType != Configuration.UI_MODE_TYPE_TELEVISION } } @@ -562,7 +562,7 @@ class SettingsFragment( } private fun openNotificationSettings() { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { requestNotificationPermissionResult.launch( Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt index 11214159fc3..dfdfd47e2a1 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/SettingsPresenterImpl.kt @@ -14,7 +14,7 @@ import io.homeassistant.companion.android.common.data.prefs.NightModeTheme import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.data.prefs.ScreenOrientation import io.homeassistant.companion.android.common.data.servers.ServerManager -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.database.settings.SettingsDao import io.homeassistant.companion.android.settings.assist.DefaultAssistantManager @@ -200,7 +200,7 @@ class SettingsPresenterImpl @Inject constructor( } // Notifications - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O) && + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O) && !NotificationManagerCompat.from(context).areNotificationsEnabled() ) { suggestions += SettingsHomeSuggestion( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt index 72840aee3c1..2a1fc9ded76 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/assist/DefaultAssistantManager.kt @@ -11,8 +11,8 @@ import dagger.hilt.android.qualifiers.ApplicationContext import io.homeassistant.companion.android.BuildConfig import io.homeassistant.companion.android.assist.service.AssistVoiceInteractionService import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import javax.inject.Inject /** @@ -61,7 +61,7 @@ class DefaultAssistantManagerImpl @Inject constructor( // Not supported on automotive if (context.isAutomotive()) return false - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { val roleManager = context.getSystemService(RoleManager::class.java) roleManager?.isRoleAvailable(RoleManager.ROLE_ASSISTANT) == true && !roleManager.isRoleHeld(RoleManager.ROLE_ASSISTANT) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt index 5c335672786..40e5109a0d6 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/ManageControlsViewModel.kt @@ -18,7 +18,7 @@ import io.homeassistant.companion.android.common.data.integration.ControlsAuthRe import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.prefs.PrefsRepository import io.homeassistant.companion.android.common.data.servers.ServerManager -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.controls.HaControlsPanelActivity import io.homeassistant.companion.android.controls.HaControlsProviderService import io.homeassistant.companion.android.database.server.Server @@ -64,7 +64,7 @@ class ManageControlsViewModel @Inject constructor( init { viewModelScope.launch { servers = serverManager.servers() - if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { panelEnabled = application.packageManager.getComponentEnabledSetting( ComponentName(application, HaControlsPanelActivity::class.java), @@ -168,7 +168,7 @@ class ManageControlsViewModel @Inject constructor( } fun enablePanelForControls(enabled: Boolean) { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) return + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) return application.packageManager.setComponentEnabledSetting( ComponentName(application, HaControlsPanelActivity::class.java), diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt index a6a8993ef3d..7ca562b6cb6 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/controls/views/ManageControlsView.kt @@ -58,7 +58,7 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.integration.ControlsAuthRequiredSetting import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.data.integration.friendlyName -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.util.compose.HaAlertWarning import io.homeassistant.companion.android.util.compose.ServerExposedDropdownMenu @@ -94,7 +94,7 @@ fun ManageControlsView( modifier = modifier, contentPadding = PaddingValues(vertical = 16.dp) + safeBottomPaddingValues(applyHorizontal = false), ) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { item { Text( text = stringResource(commonR.string.controls_setting_panel), @@ -129,7 +129,7 @@ fun ManageControlsView( } } - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) || !panelEnabled) { + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) || !panelEnabled) { if (serversList.size > 1) { item { Row( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt index 6554fe34526..50cb4df6bbd 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/language/LanguagesManager.kt @@ -6,7 +6,7 @@ import androidx.appcompat.app.AppCompatDelegate import androidx.core.os.LocaleListCompat import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.prefs.PrefsRepository -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -21,7 +21,7 @@ class LanguagesManager @Inject constructor(private var prefs: PrefsRepository) { suspend fun getCurrentLang(): String { val lang = prefs.getCurrentLang() - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { migrateLangSetting() AppCompatDelegate.getApplicationLocales().toLanguageTags().ifEmpty { DEF_LOCALE } } else { @@ -40,7 +40,7 @@ class LanguagesManager @Inject constructor(private var prefs: PrefsRepository) { withContext(Dispatchers.IO) { if (!lang.isNullOrEmpty()) { val currentLang = getCurrentLang() - if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { val languages = if (lang == DEF_LOCALE) { LocaleListCompat.getEmptyLocaleList() @@ -59,7 +59,7 @@ class LanguagesManager @Inject constructor(private var prefs: PrefsRepository) { suspend fun applyCurrentLang() { migrateLangSetting() - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { val lang = getCurrentLang() val languages = if (lang == DEF_LOCALE) { @@ -72,7 +72,7 @@ class LanguagesManager @Inject constructor(private var prefs: PrefsRepository) { } private suspend fun migrateLangSetting() { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) return + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) return val lang = prefs.getCurrentLang() if (lang == SYSTEM_MANAGES_LOCALE) return diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt index 309d3df3e2a..69e71debe3c 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/log/LogFragment.kt @@ -30,7 +30,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.R import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.prefs.PrefsRepository -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.settings.addHelpMenuProvider import io.homeassistant.companion.android.util.LogcatReader import io.homeassistant.companion.android.util.applyBottomSafeDrawingInsets @@ -201,7 +201,7 @@ class LogFragment : Fragment() { // Also no issue template will be used val excludedComponents = getExcludedComponentsForPackageName(sendIntent, arrayOf("com.github.android")) - if (excludedComponents.size > 0 && sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (excludedComponents.size > 0 && SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponents.toTypedArray()) } } @@ -238,7 +238,7 @@ class LogFragment : Fragment() { packageNames: Array, ): ArrayList { val excludedComponents = ArrayList() - val resInfos = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + val resInfos = if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { requireContext().packageManager.queryIntentActivities(sendIntent, PackageManager.ResolveInfoFlags.of(0)) } else { @Suppress("DEPRECATION") diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt index cb0e5616b8e..0d51ae11e22 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/ManageTilesViewModel.kt @@ -26,7 +26,7 @@ import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.AreaRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.DeviceRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.qs.TileDao import io.homeassistant.companion.android.database.qs.TileEntity import io.homeassistant.companion.android.database.qs.getHighestInUse @@ -229,7 +229,7 @@ class ManageTilesViewModel @Inject constructor( selectedShouldVibrate = it?.shouldVibrate ?: false tileAuthRequired = it?.authRequired ?: false submitButtonLabel = - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) || it?.added == true) { + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) || it?.added == true) { commonR.string.tile_save } else { commonR.string.tile_add @@ -297,7 +297,7 @@ class ManageTilesViewModel @Inject constructor( val highestInUse = tileDao.getHighestInUse()?.numberedId ?: 0 updateActiveTileServices(highestInUse, app) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && !selectedTileAdded) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && !selectedTileAdded) { val statusBarManager = app.getSystemService() val service = idToTileService[selectedTile.id] ?: Tile1Service::class.java val icon = selectedIcon?.let { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt index 6c92ae38ca4..0d91a155ade 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/qs/views/ManageTilesView.kt @@ -39,7 +39,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.compose.theme.HATheme -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.settings.qs.ManageTilesViewModel import io.homeassistant.companion.android.util.compose.ServerExposedDropdownMenu import io.homeassistant.companion.android.util.compose.entity.EntityPicker @@ -123,7 +123,7 @@ fun ManageTilesView( .fillMaxWidth(), ) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { TextField( value = viewModel.tileSubtitle.orEmpty(), onValueChange = { viewModel.tileSubtitle = it }, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt index e997b4e97b9..feac20171a8 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailFragment.kt @@ -27,7 +27,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.R import io.homeassistant.companion.android.common.util.DisabledLocationHandler import io.homeassistant.companion.android.common.util.LocationPermissionInfoHandler -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.sensors.HealthConnectSensorManager import io.homeassistant.companion.android.settings.sensor.views.SensorDetailView import io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme @@ -142,7 +142,7 @@ class SensorDetailFragment : Fragment() { } healthPermissionsRequest?.launch(healthConnectPermissions.toSet()) } - sdkVersion.isAtLeast(Build.VERSION_CODES.R) -> + SdkVersion.isAtLeast(Build.VERSION_CODES.R) -> if (it.permissions.size == 1 && it.permissions[0] == Manifest.permission.ACCESS_BACKGROUND_LOCATION ) { @@ -166,7 +166,7 @@ class SensorDetailFragment : Fragment() { continueYesCallback = { requestForServer = it.serverId permissionsRequest.launch( - if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.R)) { it.permissions.toSet().minus( Manifest.permission.ACCESS_BACKGROUND_LOCATION, ).toTypedArray() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt index 982aa9e58ad..96559448018 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/SensorDetailViewModel.kt @@ -24,7 +24,7 @@ import io.homeassistant.companion.android.common.sensors.BluetoothSensorManager import io.homeassistant.companion.android.common.sensors.NetworkSensorManager import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.DisabledLocationHandler -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.sensor.SensorDao import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType @@ -418,7 +418,7 @@ class SensorDetailViewModel @Inject constructor( return if (entries?.isNotEmpty() == true) { entries.map { try { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { packageManager.getApplicationInfo(it, PackageManager.ApplicationInfoFlags.of(0)) } else { @Suppress("DEPRECATION") @@ -429,7 +429,7 @@ class SensorDetailViewModel @Inject constructor( } } } else { - val appInfo = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + val appInfo = if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { packageManager?.getInstalledApplications( PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong()), ) @@ -552,7 +552,7 @@ class SensorDetailViewModel @Inject constructor( // This is only called when we requested permissions to enable a sensor, so check if we // need to do another request, or if we have all permissions and should enable the sensor. if (results.keys.contains(Manifest.permission.ACCESS_FINE_LOCATION) && - sdkVersion.isAtLeast(Build.VERSION_CODES.R) + SdkVersion.isAtLeast(Build.VERSION_CODES.R) ) { permissionRequests.value = PermissionsDialog(serverId, arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt index cbd3c86474e..625b92d2007 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/sensor/views/SensorUpdateFrequencyView.kt @@ -14,7 +14,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.util.CHANNEL_SENSOR_WORKER -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.settings.SensorUpdateFrequencySetting import io.homeassistant.companion.android.util.compose.InfoNotification import io.homeassistant.companion.android.util.compose.RadioButtonRow @@ -54,7 +54,7 @@ fun SensorUpdateFrequencyView( onClick = { onSettingChanged(SensorUpdateFrequencySetting.FAST_ALWAYS) }, ) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { InfoNotification( infoString = R.string.sensor_update_notification, channelId = CHANNEL_SENSOR_WORKER, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt index 4960862f111..09a1823fb4d 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/shortcuts/ManageShortcutsViewModel.kt @@ -40,7 +40,7 @@ import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.AreaRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.DeviceRegistryResponse import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryResponse -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.IconDialogCompat import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.util.icondialog.getIconByMdiName @@ -64,7 +64,7 @@ class ManageShortcutsViewModel @Inject constructor( val app = application val canPinShortcuts = - sdkVersion.isAtLeast(Build.VERSION_CODES.O) && ShortcutManagerCompat.isRequestPinShortcutSupported(app) + SdkVersion.isAtLeast(Build.VERSION_CODES.O) && ShortcutManagerCompat.isRequestPinShortcutSupported(app) var pinnedShortcuts = ShortcutManagerCompat.getShortcuts(app, ShortcutManagerCompat.FLAG_MATCH_PINNED) .filter { !it.id.startsWith(AssistShortcutActivity.SHORTCUT_PREFIX) } .toMutableList() @@ -170,7 +170,7 @@ class ManageShortcutsViewModel @Inject constructor( updateDynamicShortcuts() Timber.d("We have ${dynamicShortcuts.size} dynamic shortcuts") - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { Timber.d("Can we pin shortcuts: ${ShortcutManagerCompat.isRequestPinShortcutSupported(app)}") Timber.d("We have ${pinnedShortcuts.size} pinned shortcuts") } @@ -229,7 +229,7 @@ class ManageShortcutsViewModel @Inject constructor( if (isNewPinned) { Timber.d("Requesting to pin shortcut: $shortcutId") - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { ShortcutManagerCompat.requestPinShortcut(app, shortcut, null) } } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt index 19aec5a3d21..af69e9e522d 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/SsidFragment.kt @@ -19,7 +19,7 @@ import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.DisabledLocationHandler import io.homeassistant.companion.android.common.util.LocationPermissionInfoHandler -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.settings.addHelpMenuProvider import io.homeassistant.companion.android.settings.ssid.views.SsidView import io.homeassistant.companion.android.util.compose.HomeAssistantAppTheme @@ -81,7 +81,7 @@ class SsidFragment : Fragment() { return } - val permissionsToCheck = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + val permissionsToCheck = if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION) } else { arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION) @@ -90,7 +90,7 @@ class SsidFragment : Fragment() { } private fun onRequestLocationPermission() { - val permissionsToCheck: Array = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + val permissionsToCheck: Array = if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION) } else { arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION) @@ -128,9 +128,9 @@ class SsidFragment : Fragment() { } private fun requestLocationPermission() { - val permissions = if (sdkVersion.isAtLeast(Build.VERSION_CODES.R)) { + val permissions = if (SdkVersion.isAtLeast(Build.VERSION_CODES.R)) { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) // Background location will be requested later - } else if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + } else if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION) } else { arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION) @@ -141,7 +141,7 @@ class SsidFragment : Fragment() { private fun onPermissionsResult(results: Map) { if (results.keys.contains(Manifest.permission.ACCESS_FINE_LOCATION) && results[Manifest.permission.ACCESS_FINE_LOCATION] == true && - sdkVersion.isAtLeast(Build.VERSION_CODES.R) + SdkVersion.isAtLeast(Build.VERSION_CODES.R) ) { // For Android 11+ we MUST NOT request Background Location permission with fine or coarse // permissions as for Android 11 the background location request needs to be done separately diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt index f9a5fad5604..cf4252d5d20 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/ssid/views/SsidView.kt @@ -59,7 +59,7 @@ import com.mikepenz.iconics.compose.Image import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.network.WifiHelper -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.util.compose.HaAlertInfo import io.homeassistant.companion.android.util.compose.HaAlertWarning import io.homeassistant.companion.android.util.plus @@ -119,7 +119,7 @@ fun SsidView( if ( activeSsid?.isNotBlank() == true && wifiSsids.none { it == activeSsid } && - (!sdkVersion.isAtLeast(Build.VERSION_CODES.R) || activeSsid !== WifiManager.UNKNOWN_SSID) + (!SdkVersion.isAtLeast(Build.VERSION_CODES.R) || activeSsid !== WifiManager.UNKNOWN_SSID) ) { item("ssid.suggestion") { Chip( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt index 1e944ea34f1..af0a0a4db8c 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/websocket/views/WebsocketSettingView.kt @@ -21,7 +21,7 @@ import androidx.core.content.getSystemService import io.homeassistant.companion.android.BuildConfig import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.util.CHANNEL_WEBSOCKET -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.settings.WebsocketSetting import io.homeassistant.companion.android.util.compose.HaAlertWarning import io.homeassistant.companion.android.util.compose.InfoNotification @@ -114,7 +114,7 @@ fun WebsocketSettingView( ) val uiManager = context.getSystemService() if (websocketSetting != WebsocketSetting.NEVER && - sdkVersion.isAtLeast(Build.VERSION_CODES.O) && + SdkVersion.isAtLeast(Build.VERSION_CODES.O) && uiManager?.currentModeType != Configuration.UI_MODE_TYPE_TELEVISION ) { InfoNotification( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt b/app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt index 528fa7d2d2c..59867328ca7 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/settings/widgets/ManageWidgetsViewModel.kt @@ -10,7 +10,7 @@ import androidx.core.content.getSystemService import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.widget.ButtonWidgetDao import io.homeassistant.companion.android.database.widget.CameraWidgetDao import io.homeassistant.companion.android.database.widget.MediaPlayerControlsWidgetDao @@ -50,7 +50,7 @@ class ManageWidgetsViewModel @Inject constructor( } private fun checkSupportsAddingWidgets(): Boolean { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val appWidgetManager = getApplication().getSystemService() try { return appWidgetManager?.isRequestPinAppWidgetSupported ?: false diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt index 165d4a8e5e9..c3a0343759e 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/themes/NightModeManager.kt @@ -8,7 +8,7 @@ import io.homeassistant.companion.android.common.data.prefs.NightModeTheme.DARK import io.homeassistant.companion.android.common.data.prefs.NightModeTheme.LIGHT import io.homeassistant.companion.android.common.data.prefs.NightModeTheme.SYSTEM import io.homeassistant.companion.android.common.data.prefs.PrefsRepository -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import javax.inject.Inject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -27,7 +27,7 @@ class NightModeManager @Inject constructor(private val prefsRepository: PrefsRep suspend fun getCurrentNightMode(): NightModeTheme { val nightMode = prefsRepository.getCurrentNightModeTheme() return if (nightMode == null) { - val nightModeThemeToSet = if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + val nightModeThemeToSet = if (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { SYSTEM } else { LIGHT diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt index 47198e4641a..1ecc52ff10e 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/ContextExtensions.kt @@ -10,7 +10,7 @@ import androidx.activity.ComponentActivity import androidx.annotation.ColorRes import androidx.core.content.ContextCompat import androidx.core.content.getSystemService -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion fun Context.getAttribute(attr: Int, fallbackAttr: Int): Int { val value = TypedValue() @@ -26,7 +26,7 @@ fun Context.getHexForColor(@ColorRes attr: Int): String { /** @return `true` if the device has an active network configured to reach the internet (not validated) */ fun Context.hasActiveConnection(): Boolean { val cm = getSystemService() ?: return false - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { cm.activeNetwork?.let { cm.getNetworkCapabilities(it)?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) } ?: false diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt index f73ded03ab4..bca8f4c0cbb 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/DataUriDownloadManager.kt @@ -18,7 +18,7 @@ import androidx.core.app.NotificationManagerCompat import dagger.hilt.android.qualifiers.ApplicationContext import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.CHANNEL_DOWNLOADS -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import java.io.File import java.io.FileOutputStream import java.text.SimpleDateFormat @@ -104,7 +104,7 @@ class DataUriDownloadManager @Inject constructor(@param:ApplicationContext priva generated } - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { val contentValues = ContentValues().apply { put(MediaStore.Downloads.DISPLAY_NAME, fileName) put(MediaStore.Downloads.MIME_TYPE, mimetype) @@ -159,7 +159,7 @@ class DataUriDownloadManager @Inject constructor(@param:ApplicationContext priva } private fun createNotificationChannel() { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationManager = NotificationManagerCompat.from(context) val channel = NotificationChannel( CHANNEL_DOWNLOADS, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt index c5f13e86cbb..ab3a6a89bd8 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/LocationPermissionState.kt @@ -7,20 +7,20 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.MultiplePermissionsState import com.google.accompanist.permissions.rememberMultiplePermissionsState import com.google.accompanist.permissions.rememberPermissionState -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion private val foregroundLocationPermissions: List = listOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, // TODO drop this requirement https://github.com/home-assistant/android/issues/5931 - if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.S)) { Manifest.permission.BLUETOOTH_CONNECT } else { Manifest.permission.BLUETOOTH }, ) val locationPermissions: List = foregroundLocationPermissions.run { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { this + Manifest.permission.ACCESS_BACKGROUND_LOCATION } else { this @@ -49,7 +49,7 @@ val locationPermissions: List = foregroundLocationPermissions.run { @OptIn(ExperimentalPermissionsApi::class) @Composable fun rememberLocationPermission(onPermissionResult: (Boolean) -> Unit): MultiplePermissionsState { - val backgroundPermissionState = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + val backgroundPermissionState = if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { rememberPermissionState( Manifest.permission.ACCESS_BACKGROUND_LOCATION, ) { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt index 0fd0a8f902a..5d78b7dbfb5 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/compose/webview/HAWebView.kt @@ -24,7 +24,7 @@ import androidx.webkit.WebSettingsCompat import androidx.webkit.WebViewFeature import io.homeassistant.companion.android.common.data.HomeAssistantApis import io.homeassistant.companion.android.common.data.prefs.NightModeTheme -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import timber.log.Timber const val BLANK_URL = "about:blank" @@ -155,7 +155,7 @@ private fun WebView.defaultSettings() { @Suppress("DEPRECATION") private fun WebSettings.setNightModeTheme(nightModeTheme: NightModeTheme, uiMode: Int) { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK) && WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK_STRATEGY) ) { diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt index 6554f0f159c..1116e7f9f4b 100755 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/NativeMode.kt @@ -7,8 +7,8 @@ import android.view.Display import androidx.car.app.CarContext import androidx.car.app.model.Action import io.homeassistant.companion.android.common.R +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.isAutomotive -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.launch.LaunchActivity import timber.log.Timber @@ -31,7 +31,7 @@ fun startNativeActivity(carContext: CarContext) { with(carContext) { // The app must indicate the default display to be used to avoid a SecurityException on newer // Android versions. See: https://developer.android.com/training/cars/platforms/releases#android-14 - val options = if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + val options = if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { ActivityOptions.makeBasic() .setLaunchDisplayId(Display.DEFAULT_DISPLAY) .toBundle() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt b/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt index 46edc769377..8917f4a6d4d 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/util/vehicle/SettingsAction.kt @@ -12,7 +12,7 @@ import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.toAndroidIconCompat -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.settings.SettingsActivity import timber.log.Timber @@ -36,7 +36,7 @@ private fun startSettingsActivity(carContext: CarContext) { Timber.d("Starting settings activity") // The app must indicate the default display to be used to avoid a SecurityException on newer // Android versions. See: https://developer.android.com/training/cars/platforms/releases#android-14 - val options = if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + val options = if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { ActivityOptions.makeBasic() .setLaunchDisplayId(Display.DEFAULT_DISPLAY) .toBundle() diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt b/app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt index a5e2c220977..f3234cc15a5 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/websocket/WebsocketManager.kt @@ -28,7 +28,7 @@ import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.CHANNEL_WEBSOCKET import io.homeassistant.companion.android.common.util.CHANNEL_WEBSOCKET_ISSUES -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.settings.SettingsDao import io.homeassistant.companion.android.database.settings.WebsocketSetting import io.homeassistant.companion.android.notifications.MessagingManager @@ -236,7 +236,7 @@ class WebsocketManager(appContext: Context, workerParams: WorkerParameters) : * @return `true` if the foreground service was started */ private suspend fun createNotification(): Boolean { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationChannel = NotificationChannel( CHANNEL_WEBSOCKET, applicationContext.getString(R.string.websocket_setting_name), @@ -280,7 +280,7 @@ class WebsocketManager(appContext: Context, workerParams: WorkerParameters) : ) .build() return try { - val type = if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + val type = if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { ServiceInfo.FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING } else { 0 @@ -291,7 +291,7 @@ class WebsocketManager(appContext: Context, workerParams: WorkerParameters) : if (e is CancellationException) return false Timber.e(e, "Unable to setForeground due to restrictions") - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { if (notificationManager.getNotificationChannel(CHANNEL_WEBSOCKET_ISSUES) == null) { val restrictedNotificationChannel = NotificationChannel( CHANNEL_WEBSOCKET_ISSUES, diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt index 9efe11d7c4d..7e42c0459d9 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewActivity.kt @@ -99,6 +99,7 @@ import io.homeassistant.companion.android.common.util.AppVersionProvider import io.homeassistant.companion.android.common.util.FailFast import io.homeassistant.companion.android.common.util.GestureAction import io.homeassistant.companion.android.common.util.GestureDirection +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.getBooleanOrElse import io.homeassistant.companion.android.common.util.getBooleanOrNull import io.homeassistant.companion.android.common.util.getDoubleOrElse @@ -111,7 +112,6 @@ import io.homeassistant.companion.android.common.util.initializePlayer import io.homeassistant.companion.android.common.util.isAutomotive import io.homeassistant.companion.android.common.util.jsonObjectOrNull import io.homeassistant.companion.android.common.util.runFragmentTransactionIfStateSafe -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.common.util.toJsonObject import io.homeassistant.companion.android.common.util.toJsonObjectOrNull import io.homeassistant.companion.android.database.authentication.Authentication @@ -366,7 +366,7 @@ class WebViewActivity : override fun onCreate(savedInstanceState: Bundle?) { if ( intent.extras?.containsKey(EXTRA_SHOW_WHEN_LOCKED) == true && - sdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) + SdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) ) { // Allow showing this on the lock screen when using device controls panel setShowWhenLocked(intent.extras?.getBoolean(EXTRA_SHOW_WHEN_LOCKED) ?: false) @@ -676,7 +676,7 @@ class WebViewActivity : } setDownloadListener { url, _, contentDisposition, mimetype, _ -> - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q) || + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q) || ActivityCompat.checkSelfPermission( context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, @@ -784,7 +784,7 @@ class WebViewActivity : } } - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val webviewPackage = WebViewCompat.getCurrentWebViewPackage(this) Timber.d( "Current webview package ${webviewPackage?.packageName} and version ${webviewPackage?.versionName}", @@ -1365,7 +1365,7 @@ class WebViewActivity : * devices the permission does not exist and no action is taken. */ private fun maybeRequestLocalNetworkPermission() { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.CINNAMON_BUN)) return if (ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_LOCAL_NETWORK, @@ -1604,7 +1604,7 @@ class WebViewActivity : videoHeight = decor.height val bounds = Rect(0, 0, 1920, 1080) if (isVideoFullScreen or isExoFullScreen) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val mPictureInPictureParamsBuilder = PictureInPictureParams.Builder() mPictureInPictureParamsBuilder.setAspectRatio( Rational( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt b/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt index d5c5fef21bf..2af00584113 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/webview/WebViewContentScreen.kt @@ -46,7 +46,7 @@ import dev.chrisbanes.haze.materials.HazeMaterials import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.compose.theme.HATheme import io.homeassistant.companion.android.common.data.prefs.NightModeTheme -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.frontend.permissions.NotificationPermissionPrompt import io.homeassistant.companion.android.util.compose.media.player.HAMediaPlayer import io.homeassistant.companion.android.util.compose.webview.HAWebView @@ -72,7 +72,7 @@ internal fun WebViewContentScreen( nightModeTheme: NightModeTheme? = null, statusBarColor: Color? = null, backgroundColor: Color? = null, - supportsNotificationPermission: Boolean = sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU), + supportsNotificationPermission: Boolean = SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU), ) { HATheme { Scaffold( diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt index dc615f82e7b..41ce0efc856 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/button/ButtonWidgetConfigureActivity.kt @@ -30,8 +30,8 @@ import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.integration.Action import io.homeassistant.companion.android.common.data.integration.Entity import io.homeassistant.companion.android.common.util.MapAnySerializer +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.kotlinJsonMapper -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.widget.ButtonWidgetDao import io.homeassistant.companion.android.database.widget.ButtonWidgetEntity import io.homeassistant.companion.android.database.widget.WidgetBackgroundType @@ -359,7 +359,7 @@ class ButtonWidgetConfigureActivity : BaseWidgetConfigureActivity e.entityId == it.trim() } diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt index 114f6bde032..e6ef79c927c 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/widgets/template/TemplateWidgetConfigureActivity.kt @@ -15,7 +15,7 @@ import androidx.core.widget.doAfterTextChanged import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.common.R as commonR -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.widget.TemplateWidgetDao import io.homeassistant.companion.android.database.widget.TemplateWidgetEntity import io.homeassistant.companion.android.database.widget.WidgetBackgroundType @@ -147,7 +147,7 @@ class TemplateWidgetConfigureActivity : BaseWidgetConfigureActivity sdkInt >= api } + SdkVersion.sdkInt = sdkInt return PermissionManager( serverManager = serverManager, settingsDao = settingsDao, diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt index b34a3d17f03..12d9c669a61 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/bluetooth/ble/MonitoringManager.kt @@ -13,7 +13,7 @@ import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.sensors.SensorReceiverBase import io.homeassistant.companion.android.common.sensors.SensorUpdateReceiver import io.homeassistant.companion.android.common.util.CHANNEL_BEACON_MONITOR -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -80,7 +80,7 @@ class MonitoringManager { val builder = NotificationCompat.Builder(context, CHANNEL_BEACON_MONITOR) builder.setSmallIcon(R.drawable.ic_stat_ic_notification) builder.setContentTitle(context.getString(R.string.beacon_scanning)) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val channel = NotificationChannel( CHANNEL_BEACON_MONITOR, diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt index 7caf90de674..a07e0b3d5ee 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/compose/util/PainterResourceUtil.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.res.painterResource import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.toBitmap -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion /** * Loads a drawable as a Compose [Painter], with fallback support for [AdaptiveIconDrawable]. @@ -39,7 +39,7 @@ fun adaptiveIconPainterResource(@DrawableRes id: Int): Painter { val theme = LocalContext.current.theme val adaptivePainter: Painter? = remember(id, resources, theme) { - if (!sdkVersion.isAtLeast(Build.VERSION_CODES.O)) return@remember null + if (!SdkVersion.isAtLeast(Build.VERSION_CODES.O)) return@remember null val drawable = ResourcesCompat.getDrawable(resources, id, theme) as? AdaptiveIconDrawable ?: return@remember null BitmapPainter(drawable.toBitmap().asImageBitmap()) diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt index 639dbe14fb9..6a2cf876582 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/data/integration/Entity.kt @@ -17,7 +17,7 @@ import io.homeassistant.companion.android.common.data.websocket.impl.entities.Co import io.homeassistant.companion.android.common.data.websocket.impl.entities.EntityRegistryOptions import io.homeassistant.companion.android.common.util.LocalDateTimeSerializer import io.homeassistant.companion.android.common.util.MapAnySerializer -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import java.time.LocalDateTime import java.time.ZoneOffset import java.time.ZonedDateTime @@ -1205,7 +1205,7 @@ fun Entity.friendlyState( } } } - if (friendlyState == state && sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (friendlyState == state && SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { try { val stateInMillis = ZonedDateTime.parse(state, DateTimeFormatter.ISO_OFFSET_DATE_TIME) .toInstant() diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt index b4805d97bac..f14c68de3a0 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/data/network/WifiHelperImpl.kt @@ -4,7 +4,7 @@ import android.net.ConnectivityManager import android.net.NetworkCapabilities import android.net.wifi.WifiManager import android.os.Build -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import javax.inject.Inject @Suppress("DEPRECATION") @@ -26,7 +26,7 @@ class WifiHelperImpl @Inject constructor( val formattedBssid = getWifiBssid() return ( formattedSsid != null && - (!sdkVersion.isAtLeast(Build.VERSION_CODES.R) || formattedSsid !== WifiManager.UNKNOWN_SSID) && + (!SdkVersion.isAtLeast(Build.VERSION_CODES.R) || formattedSsid !== WifiManager.UNKNOWN_SSID) && formattedSsid in networks ) || ( diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt index 8cbbce3d1a6..506b337e929 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationDeleteReceiver.kt @@ -7,8 +7,8 @@ import android.os.Build import androidx.core.app.NotificationManagerCompat import dagger.hilt.android.AndroidEntryPoint import io.homeassistant.companion.android.common.data.servers.ServerManager +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.cancelGroupIfNeeded -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.notification.NotificationDao import javax.inject.Inject import kotlinx.coroutines.CoroutineScope @@ -36,7 +36,7 @@ class NotificationDeleteReceiver : BroadcastReceiver() { @Suppress("UNCHECKED_CAST") override fun onReceive(context: Context, intent: Intent) { - val hashData = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + val hashData = if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { intent.getSerializableExtra(EXTRA_DATA, HashMap::class.java) } else { @Suppress("DEPRECATION") diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt index a6176aaa5b6..c67a86d9c1b 100755 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/notifications/NotificationFunctions.kt @@ -25,8 +25,8 @@ import com.mikepenz.iconics.utils.toAndroidIconCompat import com.vdurmont.emoji.EmojiParser import io.homeassistant.companion.android.common.R import io.homeassistant.companion.android.common.util.CHANNEL_GENERAL +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.cancel -import io.homeassistant.companion.android.common.util.sdkVersion import java.util.Locale import timber.log.Timber @@ -83,7 +83,7 @@ fun handleChannel( } // Since android Oreo notification channel is needed. - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val channel = NotificationChannel( channelID, channelName, @@ -144,7 +144,7 @@ fun handleChannelSound(context: Context, channel: NotificationChannel) { } fun setChannelLedColor(context: Context, data: Map, channel: NotificationChannel) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val ledColor = data[NotificationData.LED_COLOR] if (!ledColor.isNullOrBlank()) { channel.enableLights(true) @@ -154,7 +154,7 @@ fun setChannelLedColor(context: Context, data: Map, channel: Not } fun setChannelVibrationPattern(data: Map, channel: NotificationChannel) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val vibrationPattern = data[NotificationData.VIBRATION_PATTERN] val arrVibrationPattern = parseVibrationPattern(vibrationPattern) if (arrVibrationPattern.isNotEmpty()) { diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt index 789b5dfa870..0d303308e66 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AppSensorManagerBase.kt @@ -9,7 +9,7 @@ import android.os.Process import androidx.annotation.RequiresApi import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import java.math.RoundingMode import timber.log.Timber @@ -101,7 +101,7 @@ abstract class AppSensorManagerBase : SensorManager { override suspend fun getAvailableSensors(context: Context): List { return when { - (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) -> + (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) -> listOf( currentVersion, app_rx_gb, @@ -136,7 +136,7 @@ abstract class AppSensorManagerBase : SensorManager { updateImportanceCheck(context) val usageStatsManager = context.getSystemService()!! updateAppInactive(context, usageStatsManager) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { updateAppStandbyBucket(context, usageStatsManager) } } diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt index c5c9f6b84e0..77bd94024a2 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/AudioSensorManager.kt @@ -8,7 +8,7 @@ import androidx.annotation.RequiresApi import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.STATE_UNKNOWN -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.sensor.toSensorsWithAttributes import java.util.concurrent.ConcurrentHashMap @@ -52,7 +52,7 @@ class AudioSensorManager : SensorManager { commonR.string.sensor_description_mic_muted, "mdi:microphone-off", updateType = - if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { SensorManager.BasicSensor.UpdateType.INTENT } else { SensorManager.BasicSensor.UpdateType.WORKER @@ -72,7 +72,7 @@ class AudioSensorManager : SensorManager { commonR.string.sensor_description_speakerphone, "mdi:volume-high", updateType = - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { SensorManager.BasicSensor.UpdateType.INTENT } else { SensorManager.BasicSensor.UpdateType.WORKER @@ -165,7 +165,7 @@ class AudioSensorManager : SensorManager { musicActive, volAlarm, volCall, volMusic, volRing, volNotification, volSystem, volDTMF, ) - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { allSupportedSensors.plus(volAccessibility) } else { allSupportedSensors @@ -191,7 +191,7 @@ class AudioSensorManager : SensorManager { updateVolumeNotification(context, audioManager) updateVolumeSystem(context, audioManager) updateVolumeDTMF(context, audioManager) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { updateVolumeAccessibility(context, audioManager) } } @@ -398,7 +398,7 @@ class AudioSensorManager : SensorManager { } val current = audioManager.getStreamVolume(streamType) - val min = if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + val min = if (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { audioManager.getStreamMinVolume(streamType) } else { 0 diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt index 82de885ee8d..c2e5ae30bbd 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BatterySensorManager.kt @@ -10,7 +10,7 @@ import androidx.core.content.ContextCompat import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import java.math.RoundingMode import kotlin.math.floor import timber.log.Timber @@ -147,9 +147,9 @@ class BatterySensorManager : SensorManager { ) override suspend fun getAvailableSensors(context: Context): List { - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { defaultSensorList.plus(listOf(remainingChargeTime, batteryCycles)) - } else if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + } else if (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { defaultSensorList.plus(remainingChargeTime) } else { defaultSensorList @@ -185,10 +185,10 @@ class BatterySensorManager : SensorManager { updateBatteryHealth(context, intent) updateBatteryTemperature(context, intent) updateBatteryPower(context, intent) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { updateRemainingChargeTime(context) } - if (sdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { updateBatteryCycles(context, intent) } } @@ -448,7 +448,7 @@ class BatterySensorManager : SensorManager { private suspend fun getBatteryCurrent(context: Context, batteryManager: BatteryManager): Float? { val current = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW) return if ( - (sdkVersion.isAtLeast(Build.VERSION_CODES.P) && current != Int.MIN_VALUE) || + (SdkVersion.isAtLeast(Build.VERSION_CODES.P) && current != Int.MIN_VALUE) || current != 0 ) { val dividerSetting = getNumberSetting( diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt index 6923489f2cb..30c8a582e07 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/BluetoothSensorManager.kt @@ -16,7 +16,7 @@ import io.homeassistant.companion.android.common.bluetooth.ble.MonitoringManager import io.homeassistant.companion.android.common.bluetooth.ble.TransmitterManager import io.homeassistant.companion.android.common.bluetooth.ble.name import io.homeassistant.companion.android.common.util.STATE_UNKNOWN -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.DatabaseEntryPoint import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType @@ -176,14 +176,14 @@ class BluetoothSensorManager : SensorManager { @SuppressLint("InlinedApi") override fun requiredPermissions(context: Context, sensorId: String): Array { return when { - (sensorId == bleTransmitter.id && sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { + (sensorId == bleTransmitter.id && SdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.BLUETOOTH_ADVERTISE, Manifest.permission.BLUETOOTH_CONNECT, ) } - (sensorId == beaconMonitor.id && !sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) -> { + (sensorId == beaconMonitor.id && !SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) -> { arrayOf( Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, @@ -192,7 +192,7 @@ class BluetoothSensorManager : SensorManager { ) } - (sensorId == beaconMonitor.id && !sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { + (sensorId == beaconMonitor.id && !SdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, @@ -202,7 +202,7 @@ class BluetoothSensorManager : SensorManager { ) } - (sensorId == beaconMonitor.id && sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { + (sensorId == beaconMonitor.id && SdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, @@ -212,7 +212,7 @@ class BluetoothSensorManager : SensorManager { ) } - (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { + (SdkVersion.isAtLeast(Build.VERSION_CODES.S)) -> { arrayOf( Manifest.permission.BLUETOOTH_CONNECT, ) diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt index 97f209181f9..d8c655cc5a4 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/MobileDataManager.kt @@ -9,7 +9,7 @@ import android.provider.Settings.Global.getInt import android.telephony.TelephonyManager import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion class MobileDataManager : SensorManager { @@ -44,7 +44,7 @@ class MobileDataManager : SensorManager { } override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (sensorId == mobileDataRoaming.id || sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + return if (sensorId == mobileDataRoaming.id || SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { arrayOf(Manifest.permission.READ_PHONE_STATE) } else { arrayOf() @@ -73,9 +73,9 @@ class MobileDataManager : SensorManager { var enabled = false val telephonyManager = context.applicationContext.getSystemService() if (telephonyManager?.simState == TelephonyManager.SIM_STATE_READY) { - enabled = if (sensor.id == mobileDataRoaming.id && sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + enabled = if (sensor.id == mobileDataRoaming.id && SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { telephonyManager.isDataRoamingEnabled - } else if (sensor.id == mobileDataState.id && sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + } else if (sensor.id == mobileDataState.id && SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { telephonyManager.isDataEnabled } else { getInt(context.contentResolver, settingKey, 0) == 1 diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt index 1e7af74c6f4..f790b3c6395 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/NetworkSensorManager.kt @@ -13,8 +13,8 @@ import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.getStringOrElse -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.common.util.toJsonObjectOrNull import io.homeassistant.companion.android.database.sensor.SensorSetting import io.homeassistant.companion.android.database.sensor.SensorSettingType @@ -177,7 +177,7 @@ class NetworkSensorManager : SensorManager { arrayOf() } - sdkVersion.isAtLeast(Build.VERSION_CODES.Q) -> { + SdkVersion.isAtLeast(Build.VERSION_CODES.Q) -> { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION, @@ -339,7 +339,7 @@ class NetworkSensorManager : SensorManager { deviceIp = if (conInfo == null || (conInfo.networkId == -1 && conInfo.linkSpeed == -1)) { "" } else { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { val connectivityManager = context.applicationContext.getSystemService() connectivityManager?.activeNetwork?.let { // Get the IPv4 address without prefix length @@ -623,7 +623,7 @@ class NetworkSensorManager : SensorManager { } /** Get WiFi connection info (without location data such as (B)SSID on Android >=S) */ - private fun getWifiConnectionInfo(context: Context): WifiInfo? = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + private fun getWifiConnectionInfo(context: Context): WifiInfo? = if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { val connectivityManager = context.applicationContext.getSystemService() connectivityManager?.activeNetwork?.let { val info = connectivityManager.getNetworkCapabilities(it)?.transportInfo diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt index 9c235e28513..8ae14ee9fdf 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/PhoneStateSensorManager.kt @@ -14,7 +14,7 @@ import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.STATE_UNAVAILABLE import io.homeassistant.companion.android.common.util.STATE_UNKNOWN -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import timber.log.Timber class PhoneStateSensorManager : SensorManager { @@ -128,7 +128,7 @@ class PhoneStateSensorManager : SensorManager { override suspend fun getAvailableSensors(context: Context): List { return when { ( - sdkVersion.isAtLeast(Build.VERSION_CODES.Q) && + SdkVersion.isAtLeast(Build.VERSION_CODES.Q) && context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) ) -> listOf( @@ -142,7 +142,7 @@ class PhoneStateSensorManager : SensorManager { ) ( - sdkVersion.isAtLeast(Build.VERSION_CODES.N) && + SdkVersion.isAtLeast(Build.VERSION_CODES.N) && context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS) ) -> listOf(phoneState, sim_1, sim_2, sim1DataNetworkType, sim2DataNetworkType) @@ -161,11 +161,11 @@ class PhoneStateSensorManager : SensorManager { checkPhoneState(context) updateSimSensor(context, 0) updateSimSensor(context, 1) - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { updateSignalStrength(context, 0) updateSignalStrength(context, 1) } - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { updateDataNetworkType(context, 0) updateDataNetworkType(context, 1) } @@ -235,7 +235,7 @@ class PhoneStateSensorManager : SensorManager { displayName = info.displayName?.toString() ?: info.carrierName.toString() attrs["carrier name"] = info.carrierName attrs["iso country code"] = info.countryIso - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { attrs["carrier id"] = info.carrierId attrs["mcc"] = info.mccString.toString() attrs["mnc"] = info.mncString.toString() diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt index 2c9d5949f83..54c770889ff 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorManager.kt @@ -15,8 +15,8 @@ import dagger.hilt.components.SingletonComponent import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.AnySerializer +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.kotlinJsonMapper -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.database.sensor.Attribute import io.homeassistant.companion.android.database.sensor.SensorDao import io.homeassistant.companion.android.database.sensor.SensorSetting @@ -91,14 +91,14 @@ interface SensorManager { fun checkUsageStatsPermission(context: Context): Boolean { val pm = context.packageManager - val appInfo = if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + val appInfo = if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { pm.getApplicationInfo(context.packageName, PackageManager.ApplicationInfoFlags.of(0)) } else { @Suppress("DEPRECATION") pm.getApplicationInfo(context.packageName, 0) } val appOpsManager = context.getSystemService() - val mode = if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + val mode = if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { appOpsManager?.unsafeCheckOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, appInfo.uid, appInfo.packageName) } else { @Suppress("DEPRECATION") diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt index 17961852b48..d79d3b71d58 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorReceiverBase.kt @@ -19,7 +19,7 @@ import io.homeassistant.companion.android.common.data.integration.SensorRegistra import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.data.websocket.impl.entities.GetConfigResponse import io.homeassistant.companion.android.common.util.CHANNEL_SENSOR_SYNC -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.DatabaseEntryPoint import io.homeassistant.companion.android.database.sensor.SensorDao import io.homeassistant.companion.android.database.sensor.SensorWithAttributes @@ -441,7 +441,7 @@ abstract class SensorReceiverBase : BroadcastReceiver() { } private fun createNotificationChannel(context: Context) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationManager = context.getSystemService() ?: return var notificationChannel = notificationManager.getNotificationChannel(CHANNEL_SENSOR_SYNC) diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt index a55f0a77327..d5a3f3b5f3c 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/SensorWorkerBase.kt @@ -13,7 +13,7 @@ import androidx.work.WorkerParameters import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.util.CHANNEL_SENSOR_WORKER -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.DatabaseEntryPoint import java.lang.IllegalStateException import kotlinx.coroutines.Dispatchers @@ -52,7 +52,7 @@ abstract class SensorWorkerBase(val appContext: Context, workerParams: WorkerPar val foregroundInfo = ForegroundInfo( NOTIFICATION_ID, notification, - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC } else { 0 @@ -90,7 +90,7 @@ abstract class SensorWorkerBase(val appContext: Context, workerParams: WorkerPar } protected fun createNotificationChannel() { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationChannel = NotificationChannel( CHANNEL_SENSOR_WORKER, appContext.getString(commonR.string.sensor_updates), diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt index dd836b3a15b..1eb1694c68c 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/sensors/StepsSensorManager.kt @@ -10,7 +10,7 @@ import android.hardware.SensorManager.SENSOR_DELAY_NORMAL import android.os.Build import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -52,7 +52,7 @@ class StepsSensorManager : private lateinit var mySensorManager: android.hardware.SensorManager override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { arrayOf(Manifest.permission.ACTIVITY_RECOGNITION) } else { emptyArray() diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt index 097108bbd22..8e1ccd4e801 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/DisabledLocationHandler.kt @@ -29,7 +29,7 @@ object DisabledLocationHandler { fun isLocationEnabled(context: Context): Boolean { val lm: LocationManager = context.getSystemService() ?: return false - return if (sdkVersion.isAtLeast(VERSION_CODES.P)) { + return if (SdkVersion.isAtLeast(VERSION_CODES.P)) { lm.isLocationEnabled } else { lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) || @@ -93,7 +93,7 @@ object DisabledLocationHandler { val parameters = settings.joinToString(separator = "\n") { "- $it" } - if (sdkVersion.isAtLeast(VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(VERSION_CODES.O)) { val channel = NotificationChannel( CHANNEL_LOCATION_DISABLED, context.applicationContext.getString(commonR.string.location_warn_channel), diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt index 3e707780655..939e5c13279 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/ExoPlayerExt.kt @@ -126,7 +126,7 @@ private fun createDataSourceFactory( private fun buildHttpEngineFactory(context: Context): DataSource.Factory? { // https://developer.android.com/reference/android/net/http/HttpEngine // Added in API level 34 also in S Extensions 7 - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.R) && + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.R) && SdkExtensions.getExtensionVersion(Build.VERSION_CODES.S) >= 7 ) { // Use Platform embedded Cronet via android.net.http.HttpEngine diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt index afb08e3472f..2da51b70b44 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/NotificationManagerExtensions.kt @@ -32,7 +32,7 @@ fun cancelNotificationGroupIfNeeded( id: Int, cancel: (String, Int) -> Unit, ): Boolean { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.N)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.N)) { Timber.d("Cancel notification with tag \"$tag\" and id \"$id\"") val currentActiveNotifications = notificationManager.activeNotifications diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt b/common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt index 81988e8afab..fab30f8e20c 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/database/migration/Utils.kt @@ -10,7 +10,7 @@ import androidx.core.app.NotificationManagerCompat import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.util.CHANNEL_DATABASE -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion private const val NOTIFICATION_ID = 45 private const val TAG = "AppDatabase" @@ -28,7 +28,7 @@ internal fun Cursor.map(transform: (Cursor) -> T): List { } private fun createNotificationChannel(context: Context) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.O)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O)) { val notificationManager = context.getSystemService()!! var notificationChannel = diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt b/common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt index 70906975b55..0e8e0e8363a 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/di/DataModule.kt @@ -28,9 +28,9 @@ import io.homeassistant.companion.android.common.data.prefs.PrefsRepositoryImpl import io.homeassistant.companion.android.common.data.prefs.WearPrefsRepository import io.homeassistant.companion.android.common.data.prefs.WearPrefsRepositoryImpl import io.homeassistant.companion.android.common.util.MtlsAwareDataSourceFactory +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.di.SuspendProvider import io.homeassistant.companion.android.common.util.getSharedPreferencesSuspend -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.common.util.tts.AndroidTextToSpeechEngine import io.homeassistant.companion.android.common.util.tts.TextToSpeechClient import io.homeassistant.companion.android.di.qualifiers.NamedDeviceId @@ -127,7 +127,7 @@ internal abstract class DataModule { @Provides @NamedOsVersion @Singleton - fun provideDeviceOsVersion() = sdkVersion.toString() + fun provideDeviceOsVersion() = SdkVersion.toString() @SuppressLint("HardwareIds") @Provides diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt index fe26f6645a9..5861f980a8b 100644 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/HomeAssistantApplication.kt @@ -17,8 +17,8 @@ import io.homeassistant.companion.android.common.data.keychain.KeyStoreRepositor import io.homeassistant.companion.android.common.data.keychain.NamedKeyStore import io.homeassistant.companion.android.common.sensors.AudioSensorManager import io.homeassistant.companion.android.common.util.HAStrictMode +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.common.util.configureComposeDiagnosticStackTrace -import io.homeassistant.companion.android.common.util.sdkVersion import io.homeassistant.companion.android.complications.ComplicationReceiver import io.homeassistant.companion.android.sensors.SensorReceiver import javax.inject.Inject @@ -41,14 +41,14 @@ open class HomeAssistantApplication : Application() { Timber.plant(Timber.DebugTree()) super.onCreate() - if (sdkVersion.isAtLeast(Build.VERSION_CODES.S) && + if (SdkVersion.isAtLeast(Build.VERSION_CODES.S) && BuildConfig.DEBUG && !BuildConfig.NO_STRICT_MODE ) { HAStrictMode.enable() } - Timber.i("Running ${BuildConfig.VERSION_NAME} on SDK $sdkVersion") + Timber.i("Running ${BuildConfig.VERSION_NAME} on SDK $SdkVersion") configureComposeDiagnosticStackTrace(isDebug = BuildConfig.DEBUG) @@ -105,7 +105,7 @@ open class HomeAssistantApplication : Application() { ) // Listen for microphone mute changes - if (sdkVersion.isAtLeast(Build.VERSION_CODES.P)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.P)) { ContextCompat.registerReceiver( this, sensorReceiver, @@ -115,7 +115,7 @@ open class HomeAssistantApplication : Application() { } // Listen for speakerphone state changes - if (sdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.Q)) { ContextCompat.registerReceiver( this, sensorReceiver, diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt index bd27258b3b8..8c848ccc3ed 100644 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/home/HomeActivity.kt @@ -16,7 +16,7 @@ import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import androidx.wear.protolayout.ActionBuilders import dagger.hilt.android.AndroidEntryPoint -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.home.views.DEEPLINK_PREFIX_SET_CAMERA_TILE import io.homeassistant.companion.android.home.views.DEEPLINK_PREFIX_SET_SHORTCUT_TILE import io.homeassistant.companion.android.home.views.DEEPLINK_PREFIX_SET_TEMPLATE_TILE @@ -183,7 +183,7 @@ class HomeActivity : } if ( intent.getBooleanExtra(EXTRA_FROM_ONBOARDING, false) && - sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && + SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && !NotificationManagerCompat.from(this@HomeActivity).areNotificationsEnabled() ) { permissionRequest.launch(Manifest.permission.POST_NOTIFICATIONS) diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt index 9d3ef870876..61ae0755964 100644 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/home/views/SensorUi.kt @@ -22,7 +22,7 @@ import androidx.wear.compose.material3.SwitchButton import androidx.wear.compose.material3.Text import androidx.wear.tooling.preview.devices.WearDevices import io.homeassistant.companion.android.common.sensors.SensorManager -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.sensor.Sensor import io.homeassistant.companion.android.theme.getSwitchButtonColors import io.homeassistant.companion.android.util.batterySensorManager @@ -52,7 +52,7 @@ fun SensorUi( isGranted.forEach { if ( it.key == Manifest.permission.ACCESS_FINE_LOCATION && - sdkVersion.isAtLeast(Build.VERSION_CODES.R) && + SdkVersion.isAtLeast(Build.VERSION_CODES.R) && manager.requiredPermissions( context, basicSensor.id, @@ -67,7 +67,7 @@ fun SensorUi( } if ( it.key == Manifest.permission.BODY_SENSORS && - sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && + SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU) && manager.requiredPermissions(context, basicSensor.id).contains(Manifest.permission.BODY_SENSORS) && manager.requiredPermissions( context, diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt index d53a5e70e8c..0102fe5f770 100755 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/BedtimeModeSensorManager.kt @@ -5,7 +5,7 @@ import android.os.Build import android.provider.Settings import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import timber.log.Timber class BedtimeModeSensorManager : SensorManager { @@ -40,7 +40,7 @@ class BedtimeModeSensorManager : SensorManager { } override fun hasSensor(context: Context): Boolean { - return sdkVersion.isAtLeast(Build.VERSION_CODES.R) + return SdkVersion.isAtLeast(Build.VERSION_CODES.R) } private suspend fun updateBedtimeMode(context: Context) { diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt index 36fda81c453..09b6d6800bf 100755 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HealthServicesSensorManager.kt @@ -20,7 +20,7 @@ import androidx.health.services.client.data.UserActivityState import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNKNOWN -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import java.time.Instant import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -103,7 +103,7 @@ class HealthServicesSensorManager : SensorManager { private val ioScope: CoroutineScope = CoroutineScope(Dispatchers.IO + Job()) - private val areHealthServicesSensorApisAvailable = sdkVersion.isAtLeast(Build.VERSION_CODES.R) + private val areHealthServicesSensorApisAvailable = SdkVersion.isAtLeast(Build.VERSION_CODES.R) override fun docsLink(): String { return "https://companion.home-assistant.io/docs/wear-os/sensors#health-services" diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt index b865ce9d6ff..1eb2ab6760e 100755 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/sensors/HeartRateSensorManager.kt @@ -17,7 +17,7 @@ import androidx.core.content.getSystemService import io.homeassistant.companion.android.common.R as commonR import io.homeassistant.companion.android.common.sensors.SensorManager import io.homeassistant.companion.android.common.util.STATE_UNKNOWN -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -61,7 +61,7 @@ class HeartRateSensorManager : } override fun requiredPermissions(context: Context, sensorId: String): Array { - return if (sdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { + return if (SdkVersion.isAtLeast(Build.VERSION_CODES.TIRAMISU)) { arrayOf(Manifest.permission.BODY_SENSORS, Manifest.permission.BODY_SENSORS_BACKGROUND) } else { arrayOf(Manifest.permission.BODY_SENSORS) diff --git a/wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt b/wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt index af140343f7c..1b6c4ff8c4f 100644 --- a/wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt +++ b/wear/src/main/kotlin/io/homeassistant/companion/android/tiles/TileViews.kt @@ -24,7 +24,7 @@ import androidx.wear.protolayout.material.layouts.PrimaryLayout import androidx.wear.tiles.RequestBuilders import io.homeassistant.companion.android.R import io.homeassistant.companion.android.common.R as commonR -import io.homeassistant.companion.android.common.util.sdkVersion +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.home.HomeActivity import io.homeassistant.companion.android.splash.SplashActivity @@ -33,7 +33,7 @@ const val MODIFIER_CLICK_REFRESH = "refresh" /** Performs a [VibrationEffect.EFFECT_CLICK] or equivalent on older Android versions */ fun hapticClick(context: Context) { - if (sdkVersion.isAtLeast(Build.VERSION_CODES.S)) { + if (SdkVersion.isAtLeast(Build.VERSION_CODES.S)) { val vibratorManager = context.getSystemService() val vibrator = vibratorManager?.defaultVibrator vibrator?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) From 0e0d7f01d2aaa90a9a57383e270645dc608549c4 Mon Sep 17 00:00:00 2001 From: Timothy <6560631+TimoPtr@users.noreply.github.com> Date: Wed, 27 May 2026 18:57:57 +0200 Subject: [PATCH 6/7] Force unit test to set SDK_INT when not robolectric --- .../CheckLocationDisabledUseCaseTest.kt | 3 ++ .../HomeAssistantSearcherImplTest.kt | 3 ++ ...r.kt => TestStateResetPlatformListener.kt} | 16 +++++-- ...it.platform.launcher.TestExecutionListener | 2 +- .../android/common/util/SdkVersion.kt | 23 ++++++++- ...r.kt => TestStateResetPlatformListener.kt} | 15 ++++-- ...it.platform.launcher.TestExecutionListener | 2 +- .../util/TestStateResetPlatformListener.kt | 48 +++++++++++++++++++ ...it.platform.launcher.TestExecutionListener | 1 + 9 files changed, 100 insertions(+), 13 deletions(-) rename app/src/test/kotlin/io/homeassistant/companion/android/util/{FailFastPlatformListener.kt => TestStateResetPlatformListener.kt} (61%) rename common/src/test/kotlin/io/homeassistant/companion/android/common/util/{FailFastPlatformListener.kt => TestStateResetPlatformListener.kt} (60%) create mode 100644 wear/src/test/kotlin/io/homeassistant/companion/android/util/TestStateResetPlatformListener.kt create mode 100644 wear/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener diff --git a/app/src/test/kotlin/io/homeassistant/companion/android/frontend/CheckLocationDisabledUseCaseTest.kt b/app/src/test/kotlin/io/homeassistant/companion/android/frontend/CheckLocationDisabledUseCaseTest.kt index e5a07094c26..5b9a648717e 100644 --- a/app/src/test/kotlin/io/homeassistant/companion/android/frontend/CheckLocationDisabledUseCaseTest.kt +++ b/app/src/test/kotlin/io/homeassistant/companion/android/frontend/CheckLocationDisabledUseCaseTest.kt @@ -2,9 +2,11 @@ package io.homeassistant.companion.android.frontend import android.Manifest import android.content.Context +import android.os.Build import io.homeassistant.companion.android.common.data.servers.ServerManager import io.homeassistant.companion.android.common.sensors.SensorManager.BasicSensor import io.homeassistant.companion.android.common.util.DisabledLocationHandler +import io.homeassistant.companion.android.common.util.SdkVersion import io.homeassistant.companion.android.database.server.Server import io.homeassistant.companion.android.database.server.ServerConnectionInfo import io.homeassistant.companion.android.database.server.ServerSessionInfo @@ -33,6 +35,7 @@ class CheckLocationDisabledUseCaseTest { @BeforeEach fun setUp() { + SdkVersion.sdkInt = Build.VERSION_CODES.M mockkObject(DisabledLocationHandler) mockkObject(SensorReceiver) every { SensorReceiver.MANAGERS } returns emptyList() diff --git a/app/src/test/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcherImplTest.kt b/app/src/test/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcherImplTest.kt index e94136d10fe..e833ff63831 100644 --- a/app/src/test/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcherImplTest.kt +++ b/app/src/test/kotlin/io/homeassistant/companion/android/onboarding/serverdiscovery/HomeAssistantSearcherImplTest.kt @@ -3,11 +3,13 @@ package io.homeassistant.companion.android.onboarding.serverdiscovery import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo import android.net.wifi.WifiManager +import android.os.Build import app.cash.turbine.TurbineTestContext import app.cash.turbine.test import app.cash.turbine.turbineScope import io.homeassistant.companion.android.common.data.HomeAssistantVersion import io.homeassistant.companion.android.common.util.FailFast +import io.homeassistant.companion.android.common.util.SdkVersion import io.mockk.CapturingSlot import io.mockk.Ordering import io.mockk.Runs @@ -35,6 +37,7 @@ class HomeAssistantSearcherImplTest { @BeforeEach fun setup() { + SdkVersion.sdkInt = Build.VERSION_CODES.M nsdManager = mockk(relaxed = true) wifiManager = mockk(relaxed = true) searcher = HomeAssistantSearcherImpl(nsdManager, wifiManager) diff --git a/app/src/test/kotlin/io/homeassistant/companion/android/util/FailFastPlatformListener.kt b/app/src/test/kotlin/io/homeassistant/companion/android/util/TestStateResetPlatformListener.kt similarity index 61% rename from app/src/test/kotlin/io/homeassistant/companion/android/util/FailFastPlatformListener.kt rename to app/src/test/kotlin/io/homeassistant/companion/android/util/TestStateResetPlatformListener.kt index 98df1c52f66..2fc87e59a66 100644 --- a/app/src/test/kotlin/io/homeassistant/companion/android/util/FailFastPlatformListener.kt +++ b/app/src/test/kotlin/io/homeassistant/companion/android/util/TestStateResetPlatformListener.kt @@ -2,6 +2,7 @@ package io.homeassistant.companion.android.util import io.homeassistant.companion.android.common.util.FailFast import io.homeassistant.companion.android.common.util.FailFastHandler +import io.homeassistant.companion.android.common.util.SdkVersion import org.junit.platform.launcher.TestExecutionListener import org.junit.platform.launcher.TestIdentifier @@ -24,19 +25,24 @@ internal object TestFailFastHandler : FailFastHandler { } /** - * JUnit Platform listener that installs [TestFailFastHandler] before every test. + * JUnit Platform listener that resets process-wide test state before every test. * - * [FailFast] keeps a process-wide handler, so a test that overrides it would leak its override to - * subsequent tests. Resetting the handler at the start of each test isolates them from one another - * and ensures any [FailFast] failure is surfaced as a normal test failure. + * Both [FailFast] (its handler) and [SdkVersion] (its [SdkVersion.sdkInt]) are process-wide + * singletons, so an override in one test would otherwise leak into subsequent tests. Resetting them + * at the start of each test isolates tests from one another: + * - [TestFailFastHandler] is installed so any [FailFast] failure surfaces as a normal test failure. + * - [SdkVersion.resetSdkInt] restores the default SDK level (0 in plain JVM tests), so a test that + * reaches an [SdkVersion.isAtLeast] gate without setting the level fails fast instead of silently + * inheriting a value from an earlier test. * * Registered via the JUnit Platform `ServiceLoader`, so it applies to both JUnit 4 (Vintage) and * JUnit Jupiter tests in this module. */ -class FailFastPlatformListener : TestExecutionListener { +class TestStateResetPlatformListener : TestExecutionListener { override fun executionStarted(testIdentifier: TestIdentifier) { if (testIdentifier.isTest) { FailFast.setHandler(TestFailFastHandler) + SdkVersion.resetSdkInt() } } } diff --git a/app/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener b/app/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener index 105b5157641..96f5774bc3d 100644 --- a/app/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener +++ b/app/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener @@ -1 +1 @@ -io.homeassistant.companion.android.util.FailFastPlatformListener +io.homeassistant.companion.android.util.TestStateResetPlatformListener diff --git a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersion.kt b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersion.kt index 8c1a2312dc2..b131db268b7 100644 --- a/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersion.kt +++ b/common/src/main/kotlin/io/homeassistant/companion/android/common/util/SdkVersion.kt @@ -15,7 +15,7 @@ import androidx.annotation.VisibleForTesting * `@SuppressLint("NewApi")`. * * The [sdkInt] setter is [VisibleForTesting] only: tests that need to simulate a different SDK - * level can assign it. + * level can assign it, and should call [resetSdkInt] afterwards to avoid leaking the override. */ @SuppressLint("SdkVersionAccess") object SdkVersion { @@ -24,9 +24,30 @@ object SdkVersion { @ChecksSdkIntAtLeast(parameter = 0) fun isAtLeast(version: Int): Boolean { + // On a real device SDK_INT is always non-zero, so this never fires in production. It is 0 + // only when Build.VERSION.SDK_INT is unavailable, i.e. a plain JVM unit test that reached + // this code without configuring the SDK level. FailFast surfaces that as a test failure so + // the test sets a level explicitly (or uses Robolectric with @Config(sdk = ...)) instead of + // silently treating every gate as "below version". + FailFast.failWhen(sdkInt == 0) { + "SdkVersion.sdkInt is 0: set SdkVersion.sdkInt in the test (and reset it afterwards), " + + "or use Robolectric with @Config(sdk = ...)" + } return sdkInt >= version } + /** + * Restores [sdkInt] to the real device value ([Build.VERSION.SDK_INT]). + * + * Intended for test teardown so that a value assigned via the [VisibleForTesting] setter does + * not leak into subsequent tests. In a plain JVM test this resets to 0, which makes a later + * [isAtLeast] call fail fast unless the test sets the level again. + */ + @VisibleForTesting + fun resetSdkInt() { + sdkInt = Build.VERSION.SDK_INT + } + /** Returns the device's [sdkInt] as a string, for use in diagnostic logging and registration payloads. */ override fun toString(): String { return sdkInt.toString() diff --git a/common/src/test/kotlin/io/homeassistant/companion/android/common/util/FailFastPlatformListener.kt b/common/src/test/kotlin/io/homeassistant/companion/android/common/util/TestStateResetPlatformListener.kt similarity index 60% rename from common/src/test/kotlin/io/homeassistant/companion/android/common/util/FailFastPlatformListener.kt rename to common/src/test/kotlin/io/homeassistant/companion/android/common/util/TestStateResetPlatformListener.kt index bf962bd7463..69fe7ecc529 100644 --- a/common/src/test/kotlin/io/homeassistant/companion/android/common/util/FailFastPlatformListener.kt +++ b/common/src/test/kotlin/io/homeassistant/companion/android/common/util/TestStateResetPlatformListener.kt @@ -22,19 +22,24 @@ internal object TestFailFastHandler : FailFastHandler { } /** - * JUnit Platform listener that installs [TestFailFastHandler] before every test. + * JUnit Platform listener that resets process-wide test state before every test. * - * [FailFast] keeps a process-wide handler, so a test that overrides it would leak its override to - * subsequent tests. Resetting the handler at the start of each test isolates them from one another - * and ensures any [FailFast] failure is surfaced as a normal test failure. + * Both [FailFast] (its handler) and [SdkVersion] (its [SdkVersion.sdkInt]) are process-wide + * singletons, so an override in one test would otherwise leak into subsequent tests. Resetting them + * at the start of each test isolates tests from one another: + * - [TestFailFastHandler] is installed so any [FailFast] failure surfaces as a normal test failure. + * - [SdkVersion.resetSdkInt] restores the default SDK level (0 in plain JVM tests), so a test that + * reaches an [SdkVersion.isAtLeast] gate without setting the level fails fast instead of silently + * inheriting a value from an earlier test. * * Registered via the JUnit Platform `ServiceLoader`, so it applies to both JUnit 4 (Vintage) and * JUnit Jupiter tests in this module. */ -class FailFastPlatformListener : TestExecutionListener { +class TestStateResetPlatformListener : TestExecutionListener { override fun executionStarted(testIdentifier: TestIdentifier) { if (testIdentifier.isTest) { FailFast.setHandler(TestFailFastHandler) + SdkVersion.resetSdkInt() } } } diff --git a/common/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener b/common/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener index 0941a7dcf0c..e6bebeb2219 100644 --- a/common/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener +++ b/common/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener @@ -1 +1 @@ -io.homeassistant.companion.android.common.util.FailFastPlatformListener +io.homeassistant.companion.android.common.util.TestStateResetPlatformListener diff --git a/wear/src/test/kotlin/io/homeassistant/companion/android/util/TestStateResetPlatformListener.kt b/wear/src/test/kotlin/io/homeassistant/companion/android/util/TestStateResetPlatformListener.kt new file mode 100644 index 00000000000..2fc87e59a66 --- /dev/null +++ b/wear/src/test/kotlin/io/homeassistant/companion/android/util/TestStateResetPlatformListener.kt @@ -0,0 +1,48 @@ +package io.homeassistant.companion.android.util + +import io.homeassistant.companion.android.common.util.FailFast +import io.homeassistant.companion.android.common.util.FailFastHandler +import io.homeassistant.companion.android.common.util.SdkVersion +import org.junit.platform.launcher.TestExecutionListener +import org.junit.platform.launcher.TestIdentifier + +/** + * [FailFastHandler] used during unit tests that rethrows the captured exception as an + * [AssertionError], so the JUnit runner reports it as a test failure instead of letting the + * default handler crash the JVM. + */ +internal object TestFailFastHandler : FailFastHandler { + override fun handleException(throwable: Throwable, additionalMessage: String?) { + val message = buildString { + append("Unhandled FailFast exception caught during test") + if (!additionalMessage.isNullOrBlank()) { + append(": ") + append(additionalMessage) + } + } + throw AssertionError(message, throwable) + } +} + +/** + * JUnit Platform listener that resets process-wide test state before every test. + * + * Both [FailFast] (its handler) and [SdkVersion] (its [SdkVersion.sdkInt]) are process-wide + * singletons, so an override in one test would otherwise leak into subsequent tests. Resetting them + * at the start of each test isolates tests from one another: + * - [TestFailFastHandler] is installed so any [FailFast] failure surfaces as a normal test failure. + * - [SdkVersion.resetSdkInt] restores the default SDK level (0 in plain JVM tests), so a test that + * reaches an [SdkVersion.isAtLeast] gate without setting the level fails fast instead of silently + * inheriting a value from an earlier test. + * + * Registered via the JUnit Platform `ServiceLoader`, so it applies to both JUnit 4 (Vintage) and + * JUnit Jupiter tests in this module. + */ +class TestStateResetPlatformListener : TestExecutionListener { + override fun executionStarted(testIdentifier: TestIdentifier) { + if (testIdentifier.isTest) { + FailFast.setHandler(TestFailFastHandler) + SdkVersion.resetSdkInt() + } + } +} diff --git a/wear/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener b/wear/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener new file mode 100644 index 00000000000..96f5774bc3d --- /dev/null +++ b/wear/src/test/resources/META-INF/services/org.junit.platform.launcher.TestExecutionListener @@ -0,0 +1 @@ +io.homeassistant.companion.android.util.TestStateResetPlatformListener From 644d6e6e1843e044274a18aa9d87f1a869b4ad84 Mon Sep 17 00:00:00 2001 From: Timothy <6560631+TimoPtr@users.noreply.github.com> Date: Wed, 27 May 2026 19:04:26 +0200 Subject: [PATCH 7/7] Fix lint issue after merge --- .../io/homeassistant/companion/android/launch/LaunchActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt b/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt index a280260b7a3..d085aea38d8 100644 --- a/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt +++ b/app/src/main/kotlin/io/homeassistant/companion/android/launch/LaunchActivity.kt @@ -160,7 +160,7 @@ class LaunchActivity : AppCompatActivity() { // Must run before super.onCreate so the window flag is set before the platform decides // whether to draw over the keyguard. Gated on the non-exported [LOCK_SCREEN_ALIAS_CLASS] // so external apps reaching the public LAUNCHER intent-filter cannot force this on. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 && + if (SdkVersion.isAtLeast(Build.VERSION_CODES.O_MR1) && intent.component?.className == LOCK_SCREEN_ALIAS_CLASS ) { setShowWhenLocked(true)