Fix AndroidAlarmManager dropping alarms
It was possible that the 'callback' property was set to 'null' after another alarm was already scheduled. This meant the callback function wasn't called when the next alarm went off.
This commit is contained in:
parent
1809f4a1ef
commit
cac4874f25
2 changed files with 30 additions and 14 deletions
|
@ -9,14 +9,18 @@ import android.os.Build
|
|||
import android.os.SystemClock
|
||||
import com.fsck.k9.backend.imap.SystemAlarmManager
|
||||
import com.fsck.k9.helper.AlarmManagerCompat
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
private const val ALARM_ACTION = "com.fsck.k9.backends.ALARM"
|
||||
private const val REQUEST_CODE = 1
|
||||
|
||||
private typealias Callback = () -> Unit
|
||||
|
||||
class AndroidAlarmManager(
|
||||
private val context: Context,
|
||||
private val alarmManager: AlarmManagerCompat,
|
||||
|
@ -33,17 +37,20 @@ class AndroidAlarmManager(
|
|||
PendingIntent.getBroadcast(context, REQUEST_CODE, intent, flags)
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var callback: (() -> Unit)? = null
|
||||
private val callback = AtomicReference<Callback?>(null)
|
||||
|
||||
init {
|
||||
val intentFilter = IntentFilter(ALARM_ACTION)
|
||||
context.registerReceiver(
|
||||
object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
coroutineScope.launch {
|
||||
callback?.invoke()
|
||||
callback = null
|
||||
val callback = callback.getAndSet(null)
|
||||
if (callback == null) {
|
||||
Timber.w("Alarm triggered but 'callback' was null")
|
||||
} else {
|
||||
coroutineScope.launch {
|
||||
callback.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -51,12 +58,13 @@ class AndroidAlarmManager(
|
|||
)
|
||||
}
|
||||
|
||||
override fun setAlarm(triggerTime: Long, callback: () -> Unit) {
|
||||
this.callback = callback
|
||||
override fun setAlarm(triggerTime: Long, callback: Callback) {
|
||||
this.callback.set(callback)
|
||||
alarmManager.scheduleAlarm(triggerTime, pendingIntent)
|
||||
}
|
||||
|
||||
override fun cancelAlarm() {
|
||||
callback.set(null)
|
||||
alarmManager.cancelAlarm(pendingIntent)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,14 +9,18 @@ import android.os.Build
|
|||
import android.os.SystemClock
|
||||
import com.fsck.k9.backend.imap.SystemAlarmManager
|
||||
import com.fsck.k9.helper.AlarmManagerCompat
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
private const val ALARM_ACTION = "com.fsck.k9.backends.ALARM"
|
||||
private const val REQUEST_CODE = 1
|
||||
|
||||
private typealias Callback = () -> Unit
|
||||
|
||||
class AndroidAlarmManager(
|
||||
private val context: Context,
|
||||
private val alarmManager: AlarmManagerCompat,
|
||||
|
@ -33,17 +37,20 @@ class AndroidAlarmManager(
|
|||
PendingIntent.getBroadcast(context, REQUEST_CODE, intent, flags)
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var callback: (() -> Unit)? = null
|
||||
private val callback = AtomicReference<Callback?>(null)
|
||||
|
||||
init {
|
||||
val intentFilter = IntentFilter(ALARM_ACTION)
|
||||
context.registerReceiver(
|
||||
object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
coroutineScope.launch {
|
||||
callback?.invoke()
|
||||
callback = null
|
||||
val callback = callback.getAndSet(null)
|
||||
if (callback == null) {
|
||||
Timber.w("Alarm triggered but 'callback' was null")
|
||||
} else {
|
||||
coroutineScope.launch {
|
||||
callback.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -51,12 +58,13 @@ class AndroidAlarmManager(
|
|||
)
|
||||
}
|
||||
|
||||
override fun setAlarm(triggerTime: Long, callback: () -> Unit) {
|
||||
this.callback = callback
|
||||
override fun setAlarm(triggerTime: Long, callback: Callback) {
|
||||
this.callback.set(callback)
|
||||
alarmManager.scheduleAlarm(triggerTime, pendingIntent)
|
||||
}
|
||||
|
||||
override fun cancelAlarm() {
|
||||
callback.set(null)
|
||||
alarmManager.cancelAlarm(pendingIntent)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue