diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e8046a68..e005cb6f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -65,14 +65,16 @@ kotlin { } } +private fun Provider.getInt() = get().toInt() + configure { namespace = "com.github.damontecres.wholphin" - compileSdk = 36 + compileSdk = libs.versions.compileSdk.getInt() defaultConfig { applicationId = "com.github.damontecres.wholphin" - minSdk = 23 - targetSdk = 36 + minSdk = libs.versions.minSdk.getInt() + targetSdk = libs.versions.targetSdk.getInt() versionCode = gitTags.trim().lines().size versionName = gitDescribe.trim().removePrefix("v").ifBlank { "0.0.0" } testInstrumentationRunner = "com.github.damontecres.wholphin.test.WholphinTestRunner" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6036dabd..582e000a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -4,6 +4,7 @@ android:installLocation="auto"> + diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerContent.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerContent.kt index 24a8e0ca..c25fe776 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerContent.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerContent.kt @@ -1,6 +1,10 @@ package com.github.damontecres.wholphin.ui.setup +import android.Manifest import android.content.res.Resources +import android.os.Build +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.AnimatedContent import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically @@ -67,6 +71,7 @@ import com.github.damontecres.wholphin.ui.isNotNullOrBlank import com.github.damontecres.wholphin.ui.rememberInt import com.github.damontecres.wholphin.ui.tryRequestFocus import com.github.damontecres.wholphin.util.LoadingState +import timber.log.Timber @Composable fun SwitchServerContent( @@ -294,10 +299,31 @@ private fun AddServerDialog( val state by viewModel.state.collectAsState() var showEnterAddress by remember { mutableStateOf(false) } + val permissionLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.RequestPermission(), + ) { isGranted -> + if (isGranted) { + viewModel.discoverServers() + } else { + showEnterAddress = true + } + } + LaunchedEffect(Unit) { viewModel.clearAddServerState() if (!showEnterAddress) { - viewModel.discoverServers() + if (viewModel.hasPermission) { + viewModel.discoverServers() + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CINNAMON_BUN) { + permissionLauncher.launch(Manifest.permission.ACCESS_LOCAL_NETWORK) + } else { + Timber.w( + "No ACCESS_LOCAL_NETWORK permission, but API <%s: %s", + Build.VERSION_CODES.CINNAMON_BUN, + Build.VERSION.SDK_INT, + ) + } } } diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerViewModel.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerViewModel.kt index 7098c118..53190665 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerViewModel.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/SwitchServerViewModel.kt @@ -1,7 +1,11 @@ package com.github.damontecres.wholphin.ui.setup +import android.Manifest import android.content.Context +import android.content.pm.PackageManager +import android.os.Build import android.widget.Toast +import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.github.damontecres.wholphin.R @@ -46,6 +50,17 @@ class SwitchServerViewModel private val _state = MutableStateFlow(SwitchServerState()) val state: StateFlow = _state + val hasPermission: Boolean + get() = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CINNAMON_BUN) { + ContextCompat.checkSelfPermission( + context, + Manifest.permission.ACCESS_LOCAL_NETWORK, + ) == PackageManager.PERMISSION_GRANTED + } else { + true + } + fun clearAddServerState() { _state.update { it.copy(addServerState = LoadingState.Pending) } } diff --git a/app/src/test/java/com/github/damontecres/wholphin/services/IntentServiceTest.kt b/app/src/test/java/com/github/damontecres/wholphin/services/IntentServiceTest.kt index 17c6a313..bb4904aa 100644 --- a/app/src/test/java/com/github/damontecres/wholphin/services/IntentServiceTest.kt +++ b/app/src/test/java/com/github/damontecres/wholphin/services/IntentServiceTest.kt @@ -25,8 +25,10 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config @RunWith(RobolectricTestRunner::class) +@Config(manifest = Config.NONE, sdk = [30]) class IntentServiceTest { private val api: ApiClient = mockk() private val serverRepository: ServerRepository = mockk() diff --git a/app/src/test/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModelTests.kt b/app/src/test/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModelTests.kt index adb29999..cf7ee59f 100644 --- a/app/src/test/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModelTests.kt +++ b/app/src/test/java/com/github/damontecres/wholphin/ui/playback/PlaybackViewModelTests.kt @@ -77,10 +77,12 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds @RunWith(RobolectricTestRunner::class) +@Config(manifest = Config.NONE, sdk = [30]) class PlaybackViewModelTests { private val testDispatcher = StandardTestDispatcher() diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2dbe114c..ff09b53d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -51,6 +51,10 @@ junitVersion = "1.3.0" espressoCore = "3.7.0" material = "1.14.0" +compileSdk = "37" +targetSdk = "37" +minSdk = "23" + [libraries] wholphin-extensions-mpv = { module = "com.github.damontecres.wholphin.mpv:wholphin-mpv", version.ref = "wholphin-extensions" } wholphin-extensions-ffmpeg = { module = "com.github.damontecres.wholphin.media3:decoder-ffmpeg", version.ref = "wholphin-extensions" } diff --git a/wholphin-mpv-stub/build.gradle.kts b/wholphin-mpv-stub/build.gradle.kts index 6002fba9..9017f416 100644 --- a/wholphin-mpv-stub/build.gradle.kts +++ b/wholphin-mpv-stub/build.gradle.kts @@ -2,14 +2,16 @@ plugins { alias(libs.plugins.android.library) } +private fun Provider.getInt() = get().toInt() + android { namespace = "com.github.damontecres.wholphin.mpv" compileSdk { - version = release(36) + version = release(libs.versions.compileSdk.getInt()) } defaultConfig { - minSdk = 23 + minSdk = libs.versions.minSdk.getInt() testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro")