Scenario
I have implemented an Android App Widget.
Clicking on the widget will launch a broadcast by using PendingIntent.getBroadcast(...).
I want to do a network request inside onReceive of the Broadcast Receiver.
(You ask why don't I use PendingIntent.getService(...) and launch an IntentService? Well that's a natural idea, but sadly due to background limitations, the service cannot be started if the app is not in foreground. You can take a look at this post.)
Problem
To prove it works, I have implemented a sample BroadcastReceiver:
class WidgetClickBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (context == null || intent == null) return
Log.i("Sira", "onReceive called")
val pendingResult = goAsync()
Observable.just(true).delay(3, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
Log.i("Sira", "Fake completion of network call")
pendingResult.finish()
}
}
}
Yeah it works.
However, I noticed that if I tap on the widget multiple times, multiple broadcast will be created and queued up one by one until the previous one's pendingResult.finish() is called.
This can be explained by the documentation of goAsync():
Keep in mind that the work you do here will block further broadcasts until it completes, so taking advantage of this at all excessively can be counter-productive and cause later events to be received more slowly.
So I want to know if there is a way to prevent the same broadcast from firing multiple times if it is already in the queue?
Or any other way to prevent queued up calls due to crazy clicks on the widget?
from How to stop same broadcast from queuing up?
No comments:
Post a Comment