1

I'm creating a fairly common use case of AppWidget on Android.

  • AppWidgetProvider calls onAppWidgetOptionsChanged() (stretchable widget) and onUpdate() (timed)
  • From those methods I start an IntentService. Case coming from options changed I pass the new size in the Intent.
  • The service contacts a web-service, builds the RemoteViews and calls updateAppWidget()

my main test device is a Nexus 7 (2012) running stock 4.3 (stock Launcher)

The widget does not use RemoteViewFactory and does not user AlarmManager. It's a static view with a constant time defined in XML.

It works most of the times, but sometimes the call to updateAppWidget() is completely ignored by the Launcher and no update happens on the screen. If I force close the launcher, clear it caches and re-size the widget (forcing an update) then it updates.

I believe there's something to do with frequency of update because I tricked up some stuff in the IntentService to, whenever it's resizing, only call to the last intent (when the user stops messing with the widget) and it soften a bit the issue.

Let's show some simplified code (it's very standard, i believe):

public class AlbumWidgetService extends WidgetUpdateIntentService {

   @Override
   protected void onHandleIntent(Intent intent) {
       // get's widgetID or array of IDs and pass to 'doTheJob'
   }

   private void doTheJob(int appWidgetId, int heightInDp, int widthInDp) {

      // ...
      // here goes code with pre calculations and get data
      // ...

      // create Intent and PendingIntent with some extras
      Intent intent = ... etc
      PendingIntent pi = PendingIntent.getActivity( ... etc

      // get url for some images    
      List<String> imageFilenames = getImagesFilename(albumId, totalImages);

      // Create the remote view
      RemoteViews views = new RemoteViews(getPackageName(), R.layout.album_widget);

      // ...
      // here goes a bunch of code that load bitmaps from the URLs
      // set text and colors in the remote view
      // put ImageViews into the remote view, etc
      // ...

      try {
         AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
         appWidgetManager.updateAppWidget(appWidgetId, views);
         Log.d(this, "Updating the widget id " + appWidgetId);
      } catch (Exception e) {
         // this exception happens if the RemoteView is too big, have too many bitmaps.
         // I'm already minizing this to happen with the pre calculations, but better safe than sorry
         Log.e(this, "Failed to update the widget id " + appWidgetId, e);
      }
   }

as I said, the thing mostly works (I can see the Log and I can see the on-screen result. But every once in a while it does not update after a resize, even thou I can see the Log and it did not crashes or anything.

ideas?

Budius
  • 39,391
  • 16
  • 102
  • 144
  • 1
    This always happens on a resize, never on a plain `onUpdate()`? – CommonsWare Oct 08 '13 at 13:17
  • Hi @CommonsWare good to know you're giving a help. I remember u from AppsWorld-2012 in London. To be honest I'm testing (compiling/re-flashing) all the time and I didn't have time to see the onUpdate yet. From each flash I'm making sure to clear the Launcher cache. So I only have seen on resize, but I'll probably leave a separate device to check every few hours. Also it's easier to check on resize because it changes the number of ImageView on it. On update the server might have not changed the data. – Budius Oct 08 '13 at 13:24
  • 1
    Off the cuff, this feels like a bug in the home screen implementation, or perhaps the underlying communications framework, more so than your app. If you're sure that you're calling `updateAppWidget()` with the right ID and the right `RemoteViews`, that's all that should be needed -- it's Android's and the home screen's responsibility from there. You might try dumping some info from the `RemoteViews` or adding more logging to confirm that you are consistently building a changed `RemoteViews` though. – CommonsWare Oct 08 '13 at 13:29
  • 1
    Also, what is the visual effect when the app widget is resized and your update does not take effect? For example, if you are making the app widget bigger, is the original `RemoteViews` just expanded to fill the space, or is the extra space unexpectedly blank, or what? – CommonsWare Oct 08 '13 at 13:31
  • I'm calling Log through the calls with the ID and I'm fairly certain it's the correct. The widget layout is a non-scrollable "photo grid", so the RemoteView processing is merely adding another LinearLayout (for extra row) and ImageViews into the LL (for extra cols). I'm calling `views.removeAllViews(R.id.baseLayout);` before add more rows. Even before my service kicks in, the Launcher re-layouts the existing RemoteView, so when my update is ignored the expanded RemoteView is still there. I'll Log the RemoteView number of childView before updating and report back. – Budius Oct 08 '13 at 13:36
  • hi @CommonsWare RemoteViews doesn't have getChildCount, but I've added some counters in the for loop and it is adding the right amount. At the end I'm starting to believe is some memory thing that does not get properly cleared in the Launcher because it took much longer (few minutes) to get to the bug if resizing the widget to smaller sizes (2x3 and 2x4). But then I wonder if there's anyway I can recycle the Bitmaps that existed in the previous AppWidget. Is there? – Budius Oct 08 '13 at 14:55
  • 1
    Well, your process will go "poof" in between updates usually, if there's nothing else keeping it around. The home screen's memory is not something you can directly influence. – CommonsWare Oct 08 '13 at 15:08
  • I have exactly the same problem. Sometimes my updateAppWidget calls just get ignored. Any news on this? – 最白目 Jan 30 '19 at 11:58

0 Answers0