Search code examples
androidandroid-appwidgetappwidgetprovider

Refresh AppWidget with network request using RemoteView button


tl;dr question:

How to properly refresh widget e.g. every minute making network request in background, reliably working Android 5-13 and according to policy

I have an app widget which needs to be refreshed more often than forced updatePeriodMillis and also should provide self-refresh button. Self interval refreshing is made with AlarmManager and works pretty good and under button click I have same PendingIntent:

    Intent intent = new Intent(REPORT_WIDGET_RUN_UPDATE);
    intent.setClass(context, ReportAppWidgetProvider.class);
    return PendingIntent.getBroadcast(context, 0, intent, 
        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);

On providers side onReceive gets called in both cases and I should do some network now. I'm using Volley, so its trivial, but with context passed to onReceive I'm always getting timeouts...

Few year ago I've started to use Service for this purpose, but starting Android 8 ForegroundService must be used for such case (background work, not running any Activity). I didn't wanted to show "auto-disappearing" notification to often, so I've switched to JobIntentService. It has some nasty rare bug and it's deprecated now, so even if it works pretty good I've decided to move on to WorkManager as suggesting last post under link, also official doc or some articles (e.g. this).

So now my JobIntentService becomes Worker followed by this article, Context in workers contructor works with Volley, network connection is done, feedback-broadcast is sent to provider and... After whole operation I'm getting VERY unwanted system-called android.appwidget.action.APPWIDGET_UPDATE. It's not mine action and it breaks my flow!

In Android 13 I see some suggestion in system logs why I'm getting this call

I/LauncherAppWidgetHostView: App widget created with id: 33
I/LauncherAppWidgetHostView: App widget with id: 33 loaded

So my widget after such refresh operation gets "recreated"... Behavior is exacly same on Android 10, but without above/any logs (different launcher)

My question is: how to properly refresh widget with network request in background, reliably working Android 5-13 and according to policy?

Maybe should I stick with sometimes-appearing ForegroundService as starting 13 it will be hidden anyway? As far as I remember there is some few-sec-limit for NOT-showing notification? It would be sufficient for me to make network call and then broadcast response to appwidget provider (call made with 3-4 sec. timeout thrown). Any suggestion, preferably working example appreciated


Solution

  • My guess is that you're running into the known WorkManager issue where it "restarts" your widget every time. I originally couldn't figure out what was causing this, but there are several issues reported on Google's Issue Tracker, including this one that I filed. And the workaround top fix this issue is

    to create a one-time Worker set to 10 years out, (use setInitialDelay) and set at least one constraint on it

    You can see the code in my answer here