I implemented an AlarmManager
to send notifications when user adds a due date to a Task. However, when the user turns off the device, all the alarms are lost. Now I'm updating the BroadcastReceiver
to receive an android.intent.action.BOOT_COMPLETED
and reschedule all the alarms set to each task.
My first attempt was to get an Rx Single
with all the tasks where the due date is higher than the current time inside the BroadcastReceiver
, then reschedule all the alarms. The issue is I'm not able to dispose the Observable
once the BroadcastReceiver
has no lifecycle. Also, it seems that this is not a good approach.
During my researches, the IntentService
was a good solution for this case, but I'm getting into the new WorkManager
library and the OneTimeWorkRequest
looks like a good and simple solution.
The Worker
is being called and executing correctly, but I'm not able to dispose the Observable
because the onStopped
method is never called.
Here is the implementation, based on this snippet:
class TaskAlarmWorker(context: Context, params: WorkerParameters) :
Worker(context, params), KoinComponent {
private val daoRepository: DaoRepository by inject()
private val compositeDisposable = CompositeDisposable()
override fun doWork(): Result {
Timber.d("doWork")
val result = LinkedBlockingQueue<Result>()
val disposable =
daoRepository.getTaskDao().getAllTasks().applySchedulers().subscribe(
{ result.put(Result.SUCCESS) },
{ result.put(Result.FAILURE) }
)
compositeDisposable.add(disposable)
return try {
result.take()
} catch (e: InterruptedException) {
Result.RETRY
}
}
override fun onStopped(cancelled: Boolean) {
Timber.d("onStopped")
compositeDisposable.clear()
}
}
WorkManager
a good solution for this case?Observable
correctly?WorkManager
is a good solution(even could be the best one)You should use RxWorker
instead of Worker
. here is an example:
To implement it. add androidx.work:work-rxjava2:$work_version to your build.gradle
file as dependency.
Extend your class from RxWorker
class, then override createWork()
function.
class TaskAlarmWorker(context: Context, params: WorkerParameters) :
RxWorker(context, params), KoinComponent {
private val daoRepository: DaoRepository by inject()
override fun createWork(): Single<Result> {
Timber.d("doRxWork")
return daoRepository.getTaskDao().getAllTasks()
.doOnSuccess { /* process result somehow */ }
.map { Result.success() }
.onErrorReturn { Result.failure() }
}
}
Important notes about RxWorker:
- The createWork() method is called on the main thread but returned single is subscribed on the background thread.
- You don’t need to worry about disposing the Observer since RxWorker will dispose it automatically when the work stops.
- Both returning Single with the value Result.failure() and single with an error will cause the worker to enter the failed state.
- You can override
onStopped
function to do more.
Read more :
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With