3

I am having an issue with updating AppWidgets and a confluence of limitations/bugs in android is preventing me finding a workaround.

My app widget is themeable so I need to be able to update the imageviews on it at runtime (as well as the textviews and intents). There are up to 9 imageviews that I am updating but the size of the graphics I'm using are fairly modest (max 11kb pngs). The total size of data I am pushing through the RemoteViews object should be under 100kb, well within the limit of 1mb. I think that actual drawable resources on screen end up being larger in size than the original pngs, but 10% of the limit seems reasonable enough to account for that. However, with certain phones and launchers, I am getting "FAILED BINDER TRANSACTION" errors.

There are two solutions that I have found for this:

1) Use setImageViewUri (which calls setImageURI) instead of setImageViewResource with the RemoteViews object, this gets rid of sending drawables through the RemoteViews object and loads the image from URI instead. Solves the memory error (see https://groups.google.com/forum/#!topic/android-developers/KKEyW6XdDvg/discussion )

2) Divide the updates to the app widget into multiple RemoteViews calls. So I update 3 of the images, call updateAppWidget, create a new RemoteViews object, update the next 3 images, call updateAppWidget, etc.

The problem with the 1st approach is that it only works for medium density devices. All other devices scale the images incorrectly due to a bug in the android codebase (see bug report: http://code.google.com/p/android/issues/detail?id=22590 )

The problem with the 2nd approach is that when the screen orientation changes, android destroys and recreates widget views using the last RemoteViews call which it stores in some secret place. This meams the appwidget doesn't get fully redrawn because I split my RemoteView calls up and the widget ends up unusable. There appears to be no reliable way to figure out when android is destroying and recreating the appwidgets - onConfigurationChanged in the service doesn't always fire and no Activity level call is ever made (ie. onUpdate, onReceive) that I can find. In order for the widgets to be able to be redrawn fully and correctly on orientation change, I can only use one RemoteViews (updateAppWidget) call so this solution won't work.

Does anyone have any idea how to work around this? I'm wondering if it'd be possible to implement my own RemoteViews that called a non-buggy setImageURI function (in a custom ImageView class) so that the scaling happened correctly. It seems like a lot of work just update a few widgets and I am not sure android will let me extend RemoteViews/ImageView that way.

Is there anyway to intercept android when the screen orientation changes and force it to redraw the whole widget?

Would love to hear any other suggestions or workaround ideas! Thanks.

emilie
  • 111
  • 6

1 Answers1

0

I've encountered the same problems when developing collections' AppWidgets. Many times the following would happened:

  • On rotation, the ListView entirely dissapeared;
  • The button listeners (actually called PendingIntents) stopped responding;
  • Changes in images via setImageViewResource didn't get updated;

.. and so on. I came to the same conclusion as you did: android destroys and recreates widget views using the last RemoteViews call which it stores in some secret place. After acknowledging that, it was a question of fine-timing the calls to AppWidgetManager.getInstance(context).updateAppWidget() because I wanted to disable the clickListeners (or PendingIntents) after telling the ListView to refresh itself (it was a network operation of calling web-services and retrieving a non-trivial amount of data) and wanted to enabled the listeners after the ListView finished loading while maintaining the RemoteViews fully loaded in order to handle a rotation.

I was this close to giving up and using as an alternative..

Is there anyway to intercept android when the screen orientation changes and force it to redraw the whole widget?

.. a service that does intercept Android rotation changes, unlike an AppWidget. If you're running out of options, I'd suggest you'd try it out:

public class MyWidget extends AppWidgetProvider {
@Override
    public void onConfigurationChanged(Configuration newConfig)
    {
                // insert code here
    }
}

Find out more about the service here in StackOverflow.

Community
  • 1
  • 1
Henrique de Sousa
  • 5,727
  • 49
  • 55