Sync only while the app is open.

This commit is contained in:
RallyBlock committed 2026-10-22 20:46:32 -07:00
1 parent f2dac546d0
commit ee1079a079
7 files changed
+3 -54

No files matched your search

+1 -1
View File
@@ -10,7 +10,7 @@ The gear icon opens **Car**. A new install already has the server address filled
`http://sync.sleepingliongames.com:27017` `http://sync.sleepingliongames.com:27017`
**Sync on its own** sends a save right away, checks about every 30 seconds while the app is open, and about every 15 minutes while it is closed. **Sync now** sends every car on the phone. **Sync on its own** sends a save right away and checks about every 30 seconds while the app is open. It stays quiet while the app is closed. **Sync now** sends every car on the phone.
Each car has its own token, shown on the **Car** screen. **Share token** sends that string to another phone. On the other phone, paste it under **Add a car from a token**. That phone then syncs that car. A different car gets a different token. Each car has its own token, shown on the **Car** screen. **Share token** sends that string to another phone. On the other phone, paste it under **Add a car from a token**. That phone then syncs that car. A different car gets a different token.
-1
View File
@@ -70,7 +70,6 @@ dependencies {
implementation(libs.androidx.room.runtime) implementation(libs.androidx.room.runtime)
implementation(libs.androidx.room.ktx) implementation(libs.androidx.room.ktx)
implementation(libs.kotlinx.coroutines.android) implementation(libs.kotlinx.coroutines.android)
implementation(libs.androidx.work)
ksp(libs.androidx.room.compiler) ksp(libs.androidx.room.compiler)
debugImplementation(libs.androidx.compose.ui.tooling) debugImplementation(libs.androidx.compose.ui.tooling)
testImplementation(libs.junit) testImplementation(libs.junit)
@@ -18,8 +18,7 @@ open class RacingApp : Application() {
val dao = AppDatabase.create(this).raceDao() val dao = AppDatabase.create(this).raceDao()
val preferences = SyncPreferences(this) val preferences = SyncPreferences(this)
runBlocking(Dispatchers.IO) { ensureCars(dao, preferences) } runBlocking(Dispatchers.IO) { ensureCars(dao, preferences) }
val sync = PitSync(this, dao, preferences) val sync = PitSync(dao, preferences)
repository = Repository(dao, sync, preferences) repository = Repository(dao, sync, preferences)
sync.schedule()
} }
} }
@@ -1,17 +1,10 @@
package com.racingapp.pitlog.data package com.racingapp.pitlog.data
import android.content.Context
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
import java.time.LocalTime import java.time.LocalTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.UUID import java.util.UUID
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
@@ -23,10 +16,7 @@ import org.json.JSONObject
class SyncException(message: String) : Exception(message) class SyncException(message: String) : Exception(message)
private const val WORK_NAME = "pitlog-sync"
class PitSync( class PitSync(
private val appContext: Context,
private val dao: RaceDao, private val dao: RaceDao,
private val preferences: SyncPreferences, private val preferences: SyncPreferences,
) { ) {
@@ -39,30 +29,10 @@ class PitSync(
fun saveAddress(address: String) { fun saveAddress(address: String) {
preferences.address = address.trim().trimEnd('/') preferences.address = address.trim().trimEnd('/')
schedule()
} }
fun setAutomatic(enabled: Boolean) { fun setAutomatic(enabled: Boolean) {
preferences.automatic = enabled preferences.automatic = enabled
schedule()
}
fun schedule() {
try {
val manager = WorkManager.getInstance(appContext)
if (!preferences.automatic || preferences.address.isBlank()) {
manager.cancelUniqueWork(WORK_NAME)
return
}
val request = PeriodicWorkRequestBuilder<SyncWorker>(15, TimeUnit.MINUTES)
.setConstraints(
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build(),
)
.build()
manager.enqueueUniquePeriodicWork(WORK_NAME, ExistingPeriodicWorkPolicy.UPDATE, request)
} catch (_: Exception) {
// Unit tests do not start WorkManager.
}
} }
fun launchAutomatic() { fun launchAutomatic() {
@@ -1,17 +0,0 @@
package com.racingapp.pitlog.data
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.racingapp.pitlog.RacingApp
class SyncWorker(
context: Context,
params: WorkerParameters,
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val app = applicationContext as? RacingApp ?: return Result.success()
app.repository.syncAutomatic()
return Result.success()
}
}
@@ -286,7 +286,7 @@ fun SettingsScreen(onBack: () -> Unit) {
} }
SectionLabel("Server") SectionLabel("Server")
Text( Text(
"This is the Pelican address. Every car on this phone uses it. Sync on its own sends each save right away, checks every half minute while the app is open, and about every 15 minutes while it is closed.", "This is the Pelican address. Every car on this phone uses it. Sync on its own sends each save right away and checks every half minute while the app is open.",
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
Row( Row(
-2
View File
@@ -9,7 +9,6 @@ lifecycle = "2.11.0"
activity = "1.12.4" activity = "1.12.4"
core = "1.19.1" core = "1.19.1"
coroutines = "1.10.1" coroutines = "1.10.1"
work = "2.10.1"
junit = "4.13.2" junit = "4.13.2"
robolectric = "4.16" robolectric = "4.16"
androidxTestCore = "1.6.1" androidxTestCore = "1.6.1"
@@ -32,7 +31,6 @@ androidx-room-runtime = { group = "androidx.room", name = "room-runtime", versio
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" } androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" }
androidx-work = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" }
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-test-core = { group = "androidx.test", name = "core", version.ref = "androidxTestCore" } androidx-test-core = { group = "androidx.test", name = "core", version.ref = "androidxTestCore" }