mirror of
https://github.com/vide/matedroid.git
synced 2026-01-20 00:03:17 +08:00
fix(sync): run sync worker as foreground service
The background sync was being killed by Android when the app went to background or screen turned off. This fix: - Adds FOREGROUND_SERVICE and FOREGROUND_SERVICE_DATA_SYNC permissions - Adds POST_NOTIFICATIONS permission for the sync notification - Runs DataSyncWorker as a foreground service with a notification - Creates a low-priority notification channel for sync status This ensures the sync continues even when the app is not in foreground. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
1875070a61
commit
d4f8e864ca
@@ -3,6 +3,9 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
<application
|
||||
android:name=".MateDroidApp"
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
package com.matedroid.data.sync
|
||||
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.hilt.work.HiltWorker
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ForegroundInfo
|
||||
import androidx.work.WorkerParameters
|
||||
import com.matedroid.R
|
||||
import com.matedroid.data.repository.ApiResult
|
||||
import com.matedroid.data.repository.TeslamateRepository
|
||||
import dagger.assisted.Assisted
|
||||
@@ -16,7 +23,7 @@ import kotlinx.coroutines.coroutineScope
|
||||
/**
|
||||
* Background worker for syncing stats data from TeslamateApi.
|
||||
*
|
||||
* Runs on app launch and syncs all cars in parallel:
|
||||
* Runs as a foreground service to prevent being killed when app is in background.
|
||||
* - Phase 1: Sync summaries (fast, for Quick Stats)
|
||||
* - Phase 2: Sync details (slow, for Deep Stats)
|
||||
*/
|
||||
@@ -32,11 +39,16 @@ class DataSyncWorker @AssistedInject constructor(
|
||||
companion object {
|
||||
const val TAG = "DataSyncWorker"
|
||||
const val WORK_NAME = "data_sync_work"
|
||||
const val NOTIFICATION_ID = 1001
|
||||
const val CHANNEL_ID = "sync_channel"
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
Log.d(TAG, "Starting data sync worker")
|
||||
|
||||
// Run as foreground service to prevent being killed
|
||||
setForeground(createForegroundInfo("Syncing data..."))
|
||||
|
||||
// Get list of cars
|
||||
val carsResult = teslamateRepository.getCars()
|
||||
val cars = when (carsResult) {
|
||||
@@ -74,4 +86,46 @@ class DataSyncWorker @AssistedInject constructor(
|
||||
|
||||
return if (allSuccess) Result.success() else Result.success() // Still success to not retry indefinitely
|
||||
}
|
||||
|
||||
/**
|
||||
* Create foreground info for the notification.
|
||||
*/
|
||||
private fun createForegroundInfo(progress: String): ForegroundInfo {
|
||||
val context = applicationContext
|
||||
|
||||
// Create notification channel (required for Android 8.0+)
|
||||
createNotificationChannel()
|
||||
|
||||
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setContentTitle("MateDroid Sync")
|
||||
.setContentText(progress)
|
||||
.setSmallIcon(R.drawable.ic_launcher_foreground)
|
||||
.setOngoing(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.build()
|
||||
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ForegroundInfo(
|
||||
NOTIFICATION_ID,
|
||||
notification,
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
)
|
||||
} else {
|
||||
ForegroundInfo(NOTIFICATION_ID, notification)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
"Data Sync",
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
).apply {
|
||||
description = "Background sync for stats data"
|
||||
}
|
||||
val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user