Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

appwidget freezes and refuses to update anymore: ignores updateAppWidget

So I have an app widget that is refreshing nicely, loading a new bitmap into an ImageView regularly like clockwork. Then, at some point, and silently, it will stop updating any further. I can tell from the log, and from activity at a server which my code is querying, that the widget is actually still continuing to fire regularly (via broadcasts caught by onReceive(), and doing its stuff as expected. The only thing that isn't happening is that the widget content is not updating.

So, in the code which executes when the widget fires, I'm creating a new RemoteViews and adding stuff to it, including loading a new bitmap via remoteViews.setImageViewBitmap(imageViewID, bmp), and then finally calling appWidgetManager.updateAppWidget(appWidgetId, remoteViews) to update the widget content. Works nicely... until it stops working.

I'm not sure what code to post, because the thing works just fine 99% of the time, but occasionally the updateAppWidget() stops working, for no apparent reason. Seems like it's a system issue, rather than a bug in my code, but I could be wrong.

The only thing which appears to maybe prompt this is when there are changes in connectivity, e.g. going from no signal to WiFi, maybe frequent such changes. It seems to happen more in those situations.

And once the widget freezes, the only thing which unfreezes it is restarting the device. Without restarting, even removing the widget and adding a new one doesn't work. In fact, adding a new one results in a dead widget that doesn't even respond to a click to open up the Config Activity, presumably because remoteViews.setOnClickPendingIntent(R.id.widget, configPendingIntent) is ignored like everything else in the RemoteViews I carefully construct and send to appWidgetManager.updateAppWidget().

It seems to be pretty much as described by many others here:

https://code.google.com/p/android/issues/detail?id=28216

and as yet there seems to be no known cure. The post at https://code.google.com/p/android/issues/detail?id=28216#c56 seemed to offer some promise, but I've tried calling AppWidgetHost.startListening() in various places, including at regular intervals via a repeating alarm to see if I could kickstart the widget, but nothing seems to work.

And other users (rather than developers) seem to be seeing this issue too: http://androidforums.com/threads/clock-widget-keeps-freezing-please-help.530333/

Any ideas? It's slowly driving me mad!

like image 390
drmrbrewer Avatar asked Mar 12 '15 21:03

drmrbrewer


1 Answers

remoteViews.setImageViewBitmap(imageViewID, bmp)

Don't do this. Doing this parcels the bitmap and sends the whole thing as a binder transaction. Binders are meant to transfer a small amount of data and don't handle bitmaps well. Even when the widget keeps updating, it's using more system resources than needed, and more launcher resources (the launcher has to unparcel the bitmap, at least temporarily storing both the parceled bytes and the unparceled, and it has to be done on the UI thread. But the issue you are seeing is the bug you linked, sometimes large binder transactions trigger a TransactionTooLargeException and the AppWidgetManagerService incorrectly handles this by stopping all future updates (sometimes to all widgets, sometimes just to yours).

Instead you should use setImageViewUri https://developer.android.com/reference/android/widget/RemoteViews.html#setImageViewUri(int,%20android.net.Uri) . It's a bit more work because you need to save the bitmap and then send the launcher a uri for it, though currently all or almost all launchers have READ_EXTERNAL_STORAGE so a file:/// uri to external storage might work, you should not rely on that in the future and instead should use a FileProvider https://developer.android.com/reference/android/support/v4/content/FileProvider.html

like image 96
Kevin TeslaCoil Avatar answered Sep 27 '22 16:09

Kevin TeslaCoil