Enabled StrictMode, removed several deprecations

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:45 +00:00
1 parent dca3f2c773
commit 1aefb04eb5
9 files changed
+45 -29

No files matched your search

@@ -18,6 +18,9 @@
package com.rtbishop.look4sat package com.rtbishop.look4sat
import android.app.Application import android.app.Application
import android.os.StrictMode
import android.os.StrictMode.ThreadPolicy
import android.os.StrictMode.VmPolicy
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@@ -28,6 +31,7 @@ class MainApplication : Application() {
lateinit var container: MainContainer lateinit var container: MainContainer
override fun onCreate() { override fun onCreate() {
if (BuildConfig.DEBUG) enableStrictMode()
super.onCreate() super.onCreate()
container = MainContainer(this) container = MainContainer(this)
container.mainScope.launch { checkAutoUpdate() } container.mainScope.launch { checkAutoUpdate() }
@@ -37,11 +41,21 @@ class MainApplication : Application() {
val settingsRepo = container.settingsRepo val settingsRepo = container.settingsRepo
if (settingsRepo.otherSettings.value.updateState) { if (settingsRepo.otherSettings.value.updateState) {
val timeDelta = System.currentTimeMillis() - settingsRepo.databaseState.value.timestamp val timeDelta = System.currentTimeMillis() - settingsRepo.databaseState.value.timestamp
if (timeDelta > 172800000) { // 48 hours in ms if (timeDelta > AUTO_UPDATE_DELTA_MS) {
val sdf = SimpleDateFormat("d MMM yyyy - HH:mm:ss", Locale.getDefault()) val sdf = SimpleDateFormat("d MMM yyyy - HH:mm:ss", Locale.getDefault())
println("Started periodic data update on ${sdf.format(Date())}") println("Started periodic data update on ${sdf.format(Date())}")
container.databaseRepo.updateFromRemote() container.databaseRepo.updateFromRemote()
} }
} }
} }
private fun enableStrictMode() {
StrictMode.setThreadPolicy(ThreadPolicy.Builder().detectAll().penaltyLog().build())
StrictMode.setVmPolicy(VmPolicy.Builder().detectAll().penaltyLog().build())
}
companion object {
private const val AUTO_UPDATE_DELTA_MS = 172_800_000L // 48 hours in ms
const val MAX_OKHTTP_CACHE_SIZE = 10_000_000L // 10 Megabytes
}
} }
@@ -84,7 +84,7 @@ class MainContainer(private val context: Context) {
} }
private fun provideRemoteSource(): IRemoteSource { private fun provideRemoteSource(): IRemoteSource {
val cache = Cache(context.cacheDir, 1000 * 1000 * 10L) val cache = Cache(context.cacheDir, MainApplication.MAX_OKHTTP_CACHE_SIZE)
val httpClient = OkHttpClient.Builder().cache(cache).build() val httpClient = OkHttpClient.Builder().cache(cache).build()
return RemoteSource(httpClient, Dispatchers.IO) return RemoteSource(httpClient, Dispatchers.IO)
} }
@@ -26,7 +26,8 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableDoubleStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -43,35 +44,35 @@ private fun FilterDialogPreview() {
@Composable @Composable
fun FilterDialog(hours: Int, elevation: Double, toggle: () -> Unit, save: (Int, Double) -> Unit) { fun FilterDialog(hours: Int, elevation: Double, toggle: () -> Unit, save: (Int, Double) -> Unit) {
val hoursValue = rememberSaveable { mutableStateOf(hours) } val hoursValue = rememberSaveable { mutableIntStateOf(hours) }
val elevValue = rememberSaveable { mutableStateOf(elevation) } val elevValue = rememberSaveable { mutableDoubleStateOf(elevation) }
Dialog(onDismissRequest = { toggle() }) { Dialog(onDismissRequest = { toggle() }) {
ElevatedCard { ElevatedCard {
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxWidth(1f)) { Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxWidth(1f)) {
Text(text = "Filter passes", color = MaterialTheme.colorScheme.primary) Text(text = "Filter passes", color = MaterialTheme.colorScheme.primary)
Text(text = "Show passes that occur within X hours") Text(text = "Show passes that occur within X hours")
OutlinedTextField(value = hoursValue.value.toString(), onValueChange = { newValue -> OutlinedTextField(value = hoursValue.intValue.toString(), onValueChange = { newValue ->
val hoursAhead = try { val hoursAhead = try {
newValue.toInt() newValue.toInt()
} catch (exception: Exception) { } catch (exception: Exception) {
12 12
} }
hoursValue.value = hoursAhead hoursValue.intValue = hoursAhead
}) })
Text(text = "Show passes with max elevation above") Text(text = "Show passes with max elevation above")
OutlinedTextField(value = elevValue.value.toString(), onValueChange = { newValue -> OutlinedTextField(value = elevValue.doubleValue.toString(), onValueChange = { newValue ->
val maxElevation = try { val maxElevation = try {
newValue.toDouble() newValue.toDouble()
} catch (exception: Exception) { } catch (exception: Exception) {
16.0 16.0
} }
elevValue.value = maxElevation elevValue.doubleValue = maxElevation
}) })
Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) { Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
CardButton(onClick = { toggle() }, text = "Cancel") CardButton(onClick = { toggle() }, text = "Cancel")
CardButton( CardButton(
onClick = { onClick = {
save(hoursValue.value, elevValue.value) save(hoursValue.intValue, elevValue.doubleValue)
toggle() toggle()
}, text = "Accept" }, text = "Accept"
) )
@@ -70,7 +70,7 @@ class PassesViewModel(
val millisBeforeStart = nextPass.aosTime.minus(timeNow) val millisBeforeStart = nextPass.aosTime.minus(timeNow)
val timerString = millisBeforeStart.toTimerString() val timerString = millisBeforeStart.toTimerString()
_timerText.emit(Triple("Next - Id:$catNum", name, timerString)) _timerText.emit(Triple("Next - Id:$catNum", name, timerString))
} catch (e: NoSuchElementException) { } catch (exception: NoSuchElementException) {
val lastPass = newPasses.last() val lastPass = newPasses.last()
val catNum = lastPass.catNum val catNum = lastPass.catNum
val name = lastPass.name val name = lastPass.name
@@ -18,7 +18,7 @@ package com.rtbishop.look4sat.presentation.pullRefresh
import androidx.compose.animation.core.LinearOutSlowInEasing import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -48,7 +48,7 @@ fun Modifier.pullRefreshIndicatorTransform(
properties["state"] = state properties["state"] = state
properties["scale"] = scale properties["scale"] = scale
}) { }) {
var height by remember { mutableStateOf(0) } var height by remember { mutableIntStateOf(0) }
Modifier Modifier
.onSizeChanged { height = it.height } .onSizeChanged { height = it.height }
.graphicsLayer { .graphicsLayer {
@@ -22,6 +22,7 @@ import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
@@ -103,8 +104,8 @@ class PullRefreshState internal constructor(
private val adjustedDistancePulled by derivedStateOf { distancePulled * DRAG_MULTIPLIER } private val adjustedDistancePulled by derivedStateOf { distancePulled * DRAG_MULTIPLIER }
private var _refreshing by mutableStateOf(false) private var _refreshing by mutableStateOf(false)
private var _position by mutableStateOf(0f) private var _position by mutableFloatStateOf(0f)
private var distancePulled by mutableStateOf(0f) private var distancePulled by mutableFloatStateOf(0f)
internal fun onPull(pullDelta: Float): Float { internal fun onPull(pullDelta: Float): Float {
if (this._refreshing) return 0f // Already refreshing, do nothing. if (this._refreshing) return 0f // Already refreshing, do nothing.
@@ -1,5 +1,3 @@
@file:OptIn(ExperimentalTextApi::class)
package com.rtbishop.look4sat.presentation.radar package com.rtbishop.look4sat.presentation.radar
import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.animateFloat
@@ -9,6 +7,7 @@ import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -25,7 +24,6 @@ import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.rotate import androidx.compose.ui.graphics.drawscope.rotate
import androidx.compose.ui.graphics.drawscope.translate import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.text.ExperimentalTextApi
import androidx.compose.ui.text.TextMeasurer import androidx.compose.ui.text.TextMeasurer
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText import androidx.compose.ui.text.drawText
@@ -47,7 +45,7 @@ fun RadarViewCompose(item: SatPos, items: List<SatPos>, azimElev: Pair<Float, Fl
val animSpec = infiniteRepeatable<Float>(tween(1000)) val animSpec = infiniteRepeatable<Float>(tween(1000))
val animScale = animTransition.animateFloat(16f, 64f, animSpec, label = "animScale") val animScale = animTransition.animateFloat(16f, 64f, animSpec, label = "animScale")
val measurer = rememberTextMeasurer() val measurer = rememberTextMeasurer()
val sweepDegrees = remember { mutableStateOf(0f) } val sweepDegrees = remember { mutableFloatStateOf(0f) }
val trackCreated = remember { mutableStateOf(false) } val trackCreated = remember { mutableStateOf(false) }
val trackPath = remember { mutableStateOf(Path()) } val trackPath = remember { mutableStateOf(Path()) }
val trackEffect = remember { mutableStateOf(PathEffect.cornerPathEffect(0f)) } val trackEffect = remember { mutableStateOf(PathEffect.cornerPathEffect(0f)) }
@@ -59,7 +57,7 @@ fun RadarViewCompose(item: SatPos, items: List<SatPos>, azimElev: Pair<Float, Fl
trackCreated.value = true trackCreated.value = true
} }
rotate(-azimElev.first) { rotate(-azimElev.first) {
drawSweep(center, sweepDegrees.value, radius, primaryColor) drawSweep(center, sweepDegrees.floatValue, radius, primaryColor)
drawRadar(radius, radarColor, strokeWidth, 3) drawRadar(radius, radarColor, strokeWidth, 3)
drawInfo(radius, primaryColor, measurer, 3) drawInfo(radius, primaryColor, measurer, 3)
translate(center.x, center.y) { translate(center.x, center.y) {
@@ -67,7 +65,7 @@ fun RadarViewCompose(item: SatPos, items: List<SatPos>, azimElev: Pair<Float, Fl
if (item.elevation > 0) drawPosition(item, radius, animScale.value, primaryColor) if (item.elevation > 0) drawPosition(item, radius, animScale.value, primaryColor)
drawAim(azimElev.first, azimElev.second, radius, strokeWidth, secondaryColor) drawAim(azimElev.first, azimElev.second, radius, strokeWidth, secondaryColor)
} }
sweepDegrees.value = (sweepDegrees.value + 360 / 12.0f / 60) % 360 sweepDegrees.floatValue = (sweepDegrees.floatValue + 360 / 12.0f / 60) % 360
} }
} }
} }
@@ -113,7 +111,7 @@ private fun DrawScope.drawAim(azim: Float, elev: Float, radius: Float, width: Fl
drawLine(color, center.copy(aimX, -aimY - size), center.copy(aimX, -aimY + size), width) drawLine(color, center.copy(aimX, -aimY - size), center.copy(aimX, -aimY + size), width)
drawCircle(color, size / 2, center.copy(aimX, -aimY), style = Stroke(width)) drawCircle(color, size / 2, center.copy(aimX, -aimY), style = Stroke(width))
} catch (exception: Exception) { } catch (exception: Exception) {
// Timber.d(exception) println(exception)
} }
} }
@@ -109,7 +109,7 @@ class SettingsViewModel(
databaseRepo.updateFromRemote() databaseRepo.updateFromRemote()
} catch (exception: Exception) { } catch (exception: Exception) {
_dataSettings.value = _dataSettings.value.copy(isUpdating = false) _dataSettings.value = _dataSettings.value.copy(isUpdating = false)
println(exception.printStackTrace()) println(exception)
} }
} }
@@ -119,7 +119,7 @@ class SettingsViewModel(
databaseRepo.updateFromFile(uri) databaseRepo.updateFromFile(uri)
} catch (exception: Exception) { } catch (exception: Exception) {
_dataSettings.value = _dataSettings.value.copy(isUpdating = false) _dataSettings.value = _dataSettings.value.copy(isUpdating = false)
println(exception.printStackTrace()) println(exception)
} }
} }
@@ -18,7 +18,6 @@
package com.rtbishop.look4sat.data.repository package com.rtbishop.look4sat.data.repository
import android.content.SharedPreferences import android.content.SharedPreferences
import android.location.Criteria
import android.location.LocationManager import android.location.LocationManager
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.location.LocationManagerCompat import androidx.core.location.LocationManagerCompat
@@ -66,7 +65,9 @@ class SettingsRepo(
//region # Station position settings //region # Station position settings
private val _stationPosition = MutableStateFlow(loadStationPosition()) private val _stationPosition = MutableStateFlow(loadStationPosition())
private val defaultProvider = LocationManager.PASSIVE_PROVIDER private val providerDef = LocationManager.PASSIVE_PROVIDER
private val providerGps = LocationManager.GPS_PROVIDER
private val providerNet = LocationManager.NETWORK_PROVIDER
private val executor = Executors.newSingleThreadExecutor() private val executor = Executors.newSingleThreadExecutor()
private val timeoutSignal = CancellationSignal().apply { private val timeoutSignal = CancellationSignal().apply {
setOnCancelListener { _stationPosition.value = loadStationPosition() } setOnCancelListener { _stationPosition.value = loadStationPosition() }
@@ -76,14 +77,15 @@ class SettingsRepo(
override fun setGpsPosition(): Boolean { override fun setGpsPosition(): Boolean {
if (!LocationManagerCompat.isLocationEnabled(locationManager)) return false if (!LocationManagerCompat.isLocationEnabled(locationManager)) return false
try { try {
val criteria = Criteria().apply { isCostAllowed = true } val hasGps = LocationManagerCompat.hasProvider(locationManager, providerGps)
val provider = locationManager.getBestProvider(criteria, true) ?: defaultProvider val hasNet = LocationManagerCompat.hasProvider(locationManager, providerNet)
val provider = if (hasGps) providerGps else if (hasNet) providerNet else providerDef
println("Requesting location for $provider provider") println("Requesting location for $provider provider")
LocationManagerCompat.getCurrentLocation(locationManager, provider, timeoutSignal, executor) { LocationManagerCompat.getCurrentLocation(locationManager, provider, timeoutSignal, executor) {
it?.let { setGeoPosition(it.latitude, it.longitude, it.altitude) } it?.let { setGeoPosition(it.latitude, it.longitude, it.altitude) }
} }
} catch (exception: SecurityException) { } catch (exception: SecurityException) {
println("No permissions were given") println("No permissions were given - $exception")
} }
return true return true
} }