2

Edit: I installed my app 4.x devices and there is no problem. Problem exists only with 3.x devices.

I am trying to update an AppWidget manually when a user setting changes on the device. To do so I use code similar to this:

ComponentName thisWidget = new ComponentName(this, MyAppWidget.class); 
AppWidgetManager manager = AppWidgetManager.getInstance(this); 
manager.updateAppWidget(thisWidget, updateViews);

I can tell that my AppWidget onUpdate method is being called as a result since I log some debug strings to logcat in the code. However the AppWidget itself doesn't change on the screen.

Here comes the interesting part: if I rotate my device and force a refresh of the home screen (from PORTRAIT to LANDSCAPE or vice-versa) then finally my AppWidget gets updated. However rotating the device does not trigger the onUpdate method to be called, so the AppWidget must be using the RemoteViews provided in the earlier update.

Can somebody explain me what to do to force the home screen redraw of my AppWidget when it processes an update?

I am using <uses-sdk android:minSdkVersion="11" />

public void onUpdate(Context context, AppWidgetManager appWidgetManager,
  int[] appWidgetIds) {

  // Get all ids
  ComponentName thisWidget = new ComponentName(context, MyProvider.class);
  int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
  // Build the intent to call the service
  Intent intent = new Intent(context.getApplicationContext(), MyService.class);
  intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);

  RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.appwidget_layout);

  appWidgetManager.updateAppWidget(appWidgetIds, views);

  // Update the widgets via the service
  context.startService(intent);
}

And my service:

@Override
public void onStart(Intent intent, int startId) {
    Log.i(LOG, "Called");

    this.appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext());

    this.allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);

    ComponentName thisWidget = new ComponentName(getApplicationContext(), MyProvider.class);
    int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
    Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));        
    Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));
    config = getResources().getConfiguration();

    for (int widgetId : allWidgetIds) {
        //do things like starting ASYNCs (couple of them) to fetch data from server
        //and set an adapter for the gridview
    }   

    Intent intentOpen = new Intent(getApplicationContext(), MainFragmentActivity.class);
    PendingIntent open = PendingIntent.getActivity(getApplicationContext(), 0, intentOpen, 0);
    remoteViews.setOnClickPendingIntent(R.id.widget_whole, open);
    remoteViews.setViewVisibility(R.id.widgetProgress, View.GONE);
    appWidgetManager.updateAppWidget( thisWidget, remoteViews );    
    Log.d(LOG, "sent!!");       
}
stopSelf();

super.onStart(intent, startId); }
Nik Reiman
  • 39,067
  • 29
  • 104
  • 160
erkangur
  • 2,048
  • 5
  • 21
  • 31

2 Answers2

0

This sounds like a bug in the launcher app to me. Every time you call updateAppWidget the AppWidgetManager receives the new layout and the launcher is responsible for redrawing the widget with this new layout.

The fact that when the screen is rotated onUpdate and updateAppWidget are not called, but the launcher redraws the widget with its new layout means that the AppWidgetManager has already successfully received that new layout.

When the screen is rotated the launcher is forced to redraw everything (its Activity is recreated) and that is why it shows the new layout.

And this bug is probably fixed in Android 4.0+

ra3o.ra3
  • 852
  • 1
  • 8
  • 7
-1

I would try calling invalidate() on the Views in your widget. Calling that forces the system to redraw the View.

boztalay
  • 562
  • 6
  • 17
  • RemoteViews does not have `invalidate` method. – erkangur Oct 09 '12 at 14:59
  • Oops, `notifyAppWidgetViewDataChanged()` in AppWidgetManager might do the trick. It tells the corresponding view to invalidate its data. – boztalay Oct 09 '12 at 15:16
  • nope no luck with that. I am already using `updateAppWidget` function. I tried `notifyAppWidgetViewDataChanged()` nothing changed. – erkangur Oct 09 '12 at 17:09