14

I have a widget, its setup so that when I click on it, it opens some settings in an activity.

views.setOnClickPendingIntent(R.id.btnActivate, pendingIntent);

This configures some settings for the application. What I want to achieve is to have the widget update its view to reflect the changed settings when the Activity I launch closes. Using the update interval or any other type of polling isn't appropriate for this.

I've seen a couple places here and in the android docs this code used:

appWidgetManager.updateAppWidget(mAppWidgetId, views);

But I don't know how to get the mAppWidgetId value. I tried following the example for a widget configuration activity here http://developer.android.com/guide/topics/appwidgets/index.html, but in the following code,

    Intent intent = getIntent();
Bundle extras = intent.getExtras();
if (extras != null) {
    mAppWidgetId = extras.getInt(
            AppWidgetManager.EXTRA_APPWIDGET_ID, 
            AppWidgetManager.INVALID_APPWIDGET_ID);
}

extras is always null, so I never get the AppWidgetID.

Ok, now I'm just rambling. What do you think I can do?

Jonas
  • 121,568
  • 97
  • 310
  • 388
Kratz
  • 4,280
  • 3
  • 32
  • 55

5 Answers5

18

I finally found the answer I was looking for, it was in an overload of the updateAppWidget function.

   appWidgetManager.updateAppWidget(new ComponentName(this.getPackageName(), Widget.class.getName()), views);

This let me access the widget without having to know the appWidgetID. My final code in my activity is then:

        // Create an Intent to launch ExampleActivity
    Intent intent = new Intent(this, Settings.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

    views.setOnClickPendingIntent(R.id.btnActivate, pendingIntent);

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
    appWidgetManager.updateAppWidget(new ComponentName(this.getPackageName(), Widget.class.getName()), views);
    finish();

I have to do all the same setup stuff I had to do in the onUpdate method of the Widget, but now every time I exit my activity the Widget is displaying the correct state.

Kratz
  • 4,280
  • 3
  • 32
  • 55
  • Thanks for sharing the answer!!! Where do we have to put this code, inside widget setting activity or inside widget class??? – BamsBamx Oct 10 '12 at 10:47
  • Nevermind, i put this inside updateWidget method, changed some "this" by "context" and removed ' AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this)' Now it is working... thanks! – BamsBamx Oct 10 '12 at 11:09
  • 1
    If you have multiple configurations for the widgets, you might want to try appWidgetManager.getAppWidgetIds(component) and then iterate over them. – Reese Mar 15 '13 at 04:22
  • @Kratz I am facing the same issue but not able to figure it out where to write this in my code http://stackoverflow.com/questions/15523736/app-widget-issue-while-showing-list-of-images?noredirect=1#comment22016477_15523736 – AndroidDev Mar 21 '13 at 10:18
  • it is so frustrating that this does not respect the DRY principle, there has to be a way – DoruChidean Feb 15 '16 at 16:02
14

There's another way to do it - pass the widget id in the pending intent that you use to start the activity:

Intent clickIntent=new Intent(context, MyConfigActivity.class);
clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
// you have the widgetId here, since it's your onUpdate
PendingIntent pendingIntent=PendingIntent
        .getActivity(context, 0,
                clickIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.btnActivate, pendingIntent);

Moreover, to avoid duplication of code from onUpdate(), you can broadcast an intent back to the AppWidgetProvider:

Intent intent = new Intent(this,MyAppWidgetProvider.class);
intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");

// Use an array and EXTRA_APPWIDGET_IDS instead of AppWidgetManager.EXTRA_APPWIDGET_ID,
// since it seems the onUpdate() is only fired on that:
int[] ids = {widgetId};
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,ids);
sendBroadcast(intent);
phaethon
  • 2,664
  • 1
  • 18
  • 7
11

I know this has been answered and accepted way ago. However while I was searching the same thing I came across an awesomely simple way to update the widget.

For future readers:

The best part, this works for all the instances of the widget and from any context (Activity, Service etc)

Heres the code,

Context context = this;
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_2x1);
ComponentName thisWidget = new ComponentName(context, MyWidget.class);
remoteViews.setTextViewText(R.id.my_text_view, "myText" + System.currentTimeMillis());
appWidgetManager.updateAppWidget(thisWidget, remoteViews);

Courtesy - Stuck :)

Community
  • 1
  • 1
Atul O Holic
  • 6,692
  • 4
  • 39
  • 74
1

Instead of doing the call from your activity, I prefere to send a broad cast request to the widget for updating. The onUpdate method will be triggered and all widget layouts are passed.

Here is my code below:

1- sending broad cast from the activity:

Intent intent = new Intent(ctxt, MyAppWidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);

int[] ids = {R.layout.appwidget};
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,ids);
ctxt.sendBroadcast(intent);

and now, 2- implement the onUpdate method:

Intent i = new Intent(ctxt, Settings.class);
PendingIntent pi = PendingIntent.getActivity(ctxt, 0, i, 0);

for (int widgetId : allWidgetIds) {
    RemoteViews remoteViews = new RemoteViews(ctxt.getPackageName(), widgetId);
    remoteViews.setTextViewText(R.id.statusMsg, msg);
    remoteViews.setOnClickPendingIntent(R.id.rootView, pi);
    AppWidgetManager mngr = AppWidgetManager.getInstance(ctxt);
    ComponentName wdgt = new ComponentName(ctxt, MyAppWidgetProvider.class);
    mngr.updateAppWidget(wdgt, remoteViews);
}

That is it! I wish it helps you :)

0
RemoteViews view = new RemoteViews("pakagename", R.layout.widget_layout_name);
view.setTextViewText(R.id.textView_id, String.valueOf(hr + ":" + mi)); // for setting a textview
view.setCharSequence(R.id.PunchIn, "setText", "Punch In"); //for setting a button name
view.setInt(R.id.PunchIn, "setBackgroundResource", R.color.black); //for setting button color
ComponentName theWidget = new ComponentName(getActivity(), AppWidget_name.class);
AppWidgetManager manager = AppWidgetManager.getInstance(getActivity());
manager.updateAppWidget(theWidget, view);