Ensure the service is restarted with the correct intent

This commit is contained in:
Benoit Marty 2021-01-12 16:26:52 +01:00
parent 50ba131350
commit 2ea45185d4
2 changed files with 46 additions and 17 deletions

View File

@ -184,7 +184,8 @@ abstract class SyncService : Service() {
onNetworkError( onNetworkError(
sessionId = sessionId ?: "", sessionId = sessionId ?: "",
syncTimeoutSeconds = syncTimeoutSeconds, syncTimeoutSeconds = syncTimeoutSeconds,
syncDelaySeconds = syncDelaySeconds syncDelaySeconds = syncDelaySeconds,
isPeriodic = periodic
) )
} }
// JobCancellation could be caught here when onDestroy cancels the coroutine context // JobCancellation could be caught here when onDestroy cancels the coroutine context
@ -227,7 +228,7 @@ abstract class SyncService : Service() {
abstract fun onRescheduleAsked(sessionId: String, syncTimeoutSeconds: Int, syncDelaySeconds: Int) abstract fun onRescheduleAsked(sessionId: String, syncTimeoutSeconds: Int, syncDelaySeconds: Int)
abstract fun onNetworkError(sessionId: String, syncTimeoutSeconds: Int, syncDelaySeconds: Int) abstract fun onNetworkError(sessionId: String, syncTimeoutSeconds: Int, syncDelaySeconds: Int, isPeriodic: Boolean)
override fun onBind(intent: Intent?): IBinder? { override fun onBind(intent: Intent?): IBinder? {
return null return null

View File

@ -95,16 +95,23 @@ class VectorSyncService : SyncService() {
override fun onRescheduleAsked(sessionId: String, override fun onRescheduleAsked(sessionId: String,
syncTimeoutSeconds: Int, syncTimeoutSeconds: Int,
syncDelaySeconds: Int) { syncDelaySeconds: Int) {
rescheduleSyncService(sessionId, syncTimeoutSeconds, syncDelaySeconds, false) rescheduleSyncService(
sessionId = sessionId,
syncTimeoutSeconds = syncTimeoutSeconds,
syncDelaySeconds = syncDelaySeconds,
isPeriodic = true,
isNetworkBack = false
)
} }
override fun onNetworkError(sessionId: String, override fun onNetworkError(sessionId: String,
syncTimeoutSeconds: Int, syncTimeoutSeconds: Int,
syncDelaySeconds: Int) { syncDelaySeconds: Int,
isPeriodic: Boolean) {
Timber.d("## Sync: A network error occurred during sync") Timber.d("## Sync: A network error occurred during sync")
val rescheduleSyncWorkRequest: WorkRequest = val rescheduleSyncWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<RestartWhenNetworkOn>() OneTimeWorkRequestBuilder<RestartWhenNetworkOn>()
.setInputData(RestartWhenNetworkOn.createInputData(sessionId, syncTimeoutSeconds, syncDelaySeconds)) .setInputData(RestartWhenNetworkOn.createInputData(sessionId, syncTimeoutSeconds, syncDelaySeconds, isPeriodic))
.setConstraints(Constraints.Builder() .setConstraints(Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) .setRequiredNetworkType(NetworkType.CONNECTED)
.build() .build()
@ -135,23 +142,36 @@ class VectorSyncService : SyncService() {
val sessionId = inputData.getString(KEY_SESSION_ID) ?: return Result.failure() val sessionId = inputData.getString(KEY_SESSION_ID) ?: return Result.failure()
val timeout = inputData.getInt(KEY_TIMEOUT, BackgroundSyncMode.DEFAULT_SYNC_TIMEOUT_SECONDS) val timeout = inputData.getInt(KEY_TIMEOUT, BackgroundSyncMode.DEFAULT_SYNC_TIMEOUT_SECONDS)
val delay = inputData.getInt(KEY_DELAY, BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS) val delay = inputData.getInt(KEY_DELAY, BackgroundSyncMode.DEFAULT_SYNC_DELAY_SECONDS)
applicationContext.rescheduleSyncService(sessionId, timeout, delay, true) val isPeriodic = inputData.getBoolean(KEY_IS_PERIODIC, false)
applicationContext.rescheduleSyncService(
sessionId = sessionId,
syncTimeoutSeconds = timeout,
syncDelaySeconds = delay,
isPeriodic = isPeriodic,
isNetworkBack = true
)
// Indicate whether the work finished successfully with the Result // Indicate whether the work finished successfully with the Result
return Result.success() return Result.success()
} }
companion object { companion object {
fun createInputData(sessionId: String, timeout: Int, delay: Int): Data { fun createInputData(sessionId: String,
timeout: Int,
delay: Int,
isPeriodic: Boolean
): Data {
return Data.Builder() return Data.Builder()
.putString(KEY_SESSION_ID, sessionId) .putString(KEY_SESSION_ID, sessionId)
.putInt(KEY_TIMEOUT, timeout) .putInt(KEY_TIMEOUT, timeout)
.putInt(KEY_DELAY, delay) .putInt(KEY_DELAY, delay)
.putBoolean(KEY_IS_PERIODIC, isPeriodic)
.build() .build()
} }
private const val KEY_SESSION_ID = "sessionId" private const val KEY_SESSION_ID = "sessionId"
private const val KEY_TIMEOUT = "timeout" private const val KEY_TIMEOUT = "timeout"
private const val KEY_DELAY = "delay" private const val KEY_DELAY = "delay"
private const val KEY_IS_PERIODIC = "isPeriodic"
} }
} }
} }
@ -159,24 +179,32 @@ class VectorSyncService : SyncService() {
private fun Context.rescheduleSyncService(sessionId: String, private fun Context.rescheduleSyncService(sessionId: String,
syncTimeoutSeconds: Int, syncTimeoutSeconds: Int,
syncDelaySeconds: Int, syncDelaySeconds: Int,
isPeriodic: Boolean,
isNetworkBack: Boolean) { isNetworkBack: Boolean) {
Timber.d("## Sync: rescheduleSyncService") Timber.d("## Sync: rescheduleSyncService")
val periodicIntent = VectorSyncService.newPeriodicIntent( val intent = if (isPeriodic) {
VectorSyncService.newPeriodicIntent(
context = this, context = this,
sessionId = sessionId, sessionId = sessionId,
syncTimeoutSeconds = syncTimeoutSeconds, syncTimeoutSeconds = syncTimeoutSeconds,
syncDelaySeconds = syncDelaySeconds, syncDelaySeconds = syncDelaySeconds,
isNetworkBack = isNetworkBack isNetworkBack = isNetworkBack
) )
} else {
VectorSyncService.newOneShotIntent(
context = this,
sessionId = sessionId
)
}
if (isNetworkBack || syncDelaySeconds == 0) { if (isNetworkBack || syncDelaySeconds == 0) {
// Do not wait, do the sync now (more reactivity if network back is due to user action) // Do not wait, do the sync now (more reactivity if network back is due to user action)
startService(periodicIntent) startService(intent)
} else { } else {
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PendingIntent.getForegroundService(this, 0, periodicIntent, 0) PendingIntent.getForegroundService(this, 0, intent, 0)
} else { } else {
PendingIntent.getService(this, 0, periodicIntent, 0) PendingIntent.getService(this, 0, intent, 0)
} }
val firstMillis = System.currentTimeMillis() + syncDelaySeconds * 1000L val firstMillis = System.currentTimeMillis() + syncDelaySeconds * 1000L
val alarmMgr = getSystemService<AlarmManager>()!! val alarmMgr = getSystemService<AlarmManager>()!!