Programmatically update widget from activity/service/receiver
Asked Answered
M

10

109

I know it's possible, but I can't figure out a way to trigger an update of my widget from the main activity. Isn't there some general intent I can broadcast?

Misgive answered 11/8, 2010 at 3:43 Comment(0)
M
217

If you are using an AppWidgetProvider, you can update it this way:

Intent intent = new Intent(this, MyAppWidgetProvider.class);
intent.setAction(AppWidgetManager.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 = AppWidgetManager.getInstance(getApplication())
    .getAppWidgetI‌​ds(new ComponentName(getApplication(), MyAppWidgetProvider.class));
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
sendBroadcast(intent);
Muntjac answered 12/10, 2011 at 10:31 Comment(11)
Where do you set widgetId?Putnam
Does the AppWidgetProvider then execute the onUpdate() method?Mindymine
@KrisB from the answer below, get the array by doing this: int ids[] = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), WidgetProvider.class));Altercate
@Muntjac i am also facing the same problem, and i used ur code to update app widget on activity finish, But in my case it called the onUpdate() method of widget provider class, but after that failed to call the RemoteViewsService class. My code snapshot is this #15524236Steamtight
It call the onRecieve override method. But question is about how to call onUpdate method.Fisticuffs
You can use a constant, no need to hardcode: intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);Instantly
Great answer. Since ids is required only for the sake of firing onUpdate at least in my case, I just fake an id as following:int[] ids = {0}; I obtain all the real widget IDs in my service class.Carbolize
i have added the above code. it calls onUpdateMethod(), but its not refreshing the list-view with newly updated database values.Kramlich
DON'T follow @gelupa comment to use R.xml.mywidget for widgetID! It is COMPLETELY wrong and just cost me 4hours of debugging!!! USE MobileMon solution to get correct widgetIDProfound
for ids: ` int widgetIDs[] = AppWidgetManager.getInstance(activity).getAppWidgetIds(new ComponentName(activity, widget.class));`Hexagon
Easily converted to Xamarin (C#). Only issue was on creating the ComponentName had to use "Java.Lang.Class.FromType(typeof(MyAppWidgetProvider)).Name".Florindaflorine
W
81

This helped when I searched on how to update a widget from a service/or action (but may be possible from every Context):

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);
Widener answered 10/12, 2010 at 20:21 Comment(3)
I know I'm jumping in here like 6 months late. But I agree with Andrew. I tried the original method in this thread. And something about how the IDs are grabbed caused it to start failing. This method (of directly updating the fields manually) works better. For my purposes, at least.Preachy
Awesome stuff. Dont know how you ended up with this but works fine and smooth for all the instances of my Widget. :)Anvil
this worked for me as well. I thought we would need to do broadcast and onReceive, but my requirements fit perfectly with thisTelethermometer
I
34

So to update an widget from an activity, you can do it like this:

Intent intent = new Intent(this, DppWidget.class);
intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
int ids[] = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), DppWidget.class));
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS,ids);
sendBroadcast(intent);

Works for me :)

Ionic answered 10/1, 2013 at 11:32 Comment(1)
It call the onRecieve override method. But i want how to call onUpdate method.Nambypamby
D
28

Try this:

int[] ids = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), MyWidget.class));
        MyWidget myWidget = new MyWidget();
        myWidget.onUpdate(this, AppWidgetManager.getInstance(this),ids);
Des answered 5/3, 2014 at 21:36 Comment(4)
Amazingly, only this little answer solved it. I still don't know the implications of instantiating the Widget class and directly calling the onUpdate method, but hey, it finally works :)Reciprocate
Thanks. I am testing it out now and will post feedback. Tested and confirmed working. I am wondering through, if there are different types of widgets, will it work the same? (+1 by the way for working)Reckon
i get always ids 0Bantustan
This will not work on Android Oreo any workaround fix?Sather
M
15

In case you are working with a widget that uses a collection such as ListView, GridView, or StackView, to update the widget's items, do as follow:

Context context = getApplicationContext();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisWidget = new ComponentName(context, StackWidgetProvider.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.stack_view);

With this method notifyAppWidgetViewDataChanged(), you can force the widget items to fetch any new data in real time.

Metameric answered 2/7, 2014 at 1:19 Comment(0)
D
13
int widgetIDs[] = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), WidgetProvider.class));

for (int id : widgetIDs)
    AppWidgetManager.getInstance(getApplication()).notifyAppWidgetViewDataChanged(id, R.id.widget_view);
}
Deceptive answered 5/9, 2012 at 12:13 Comment(2)
Requires min-api level: 11.Guyon
Awesome. You don't even have to loop, there's a version of notifyAppWidgetViewDataChanged() that takes an array.Sweetheart
F
6

Phaethon's accepted solution in Kotlin:

val intent = Intent(this, MyAppWidgetProvider::class.java)
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
val ids = AppWidgetManager.getInstance(application).getAppWidgetIds(ComponentName(getApplicationContext(),MyAppWidgetProvider::class.java!!))
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
sendBroadcast(intent)

Where MyAppWidgetProvider is derived from AppWidgetProvider:

MyAppWidgetProvider : AppWidgetProvider() {
Foreside answered 18/4, 2018 at 13:20 Comment(0)
N
5

If you are trying to programmatically update the widget where you do not have access to YourWidgetProvider.class explicitly, e.g. from another module or library, you can capture what YourWidgetProvider.class.getName() outputs and create a constant:

val WIDGET_CLASS_NAME = "com.example.yourapplication.YourWidgetProvider"

You would then be able to use this implicitly:

val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
val widgetManager = AppWidgetManager.getInstance(context)
val ids = widgetManager.getAppWidgetIds(ComponentName(context, WIDGET_CLASS_NAME))
AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(ids, android.R.id.list)
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
context.sendBroadcast(intent)
Nubia answered 16/1, 2020 at 1:4 Comment(0)
C
1

For reference, I had to do like this in a fragment:

Application app = getActivity().getApplication();
Intent intent = new Intent(context, RQWidget.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);

int[] ids = AppWidgetManager.getInstance(app).getAppWidgetIds(new ComponentName(app, RQWidget.class));
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
context.sendBroadcast(intent);
Clarkclarke answered 29/11, 2020 at 14:49 Comment(0)
J
1

Example from my to-do list:

Intent intent = new Intent(this, TodosAppWidget.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
int[] ids = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), TodosAppWidget.class));
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
sendBroadcast(intent);
sendBrodcast(Intent(this, TodosAppWidget::class.java).apply {
  action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
  val ids = AppWidgetManager.getInstance(application).getAppWidgetIds(ComponentName(application, TodosAppWidget::class.java))
  putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
})
Janycejanyte answered 25/5, 2021 at 19:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.