以编程方式从活动/服务/接收方更新小部件

我知道这是可能的,但我不能找到一种方法来触发我的小部件从主活动的更新。难道没有一些我可以广播的总体意图吗?

75268 次浏览

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);

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);
int widgetIDs[] = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), WidgetProvider.class));


for (int id : widgetIDs)
AppWidgetManager.getInstance(getApplication()).notifyAppWidgetViewDataChanged(id, R.id.widget_view);
}

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 :)

Try this:

int[] ids = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), MyWidget.class));
MyWidget myWidget = new MyWidget();
myWidget.onUpdate(this, AppWidgetManager.getInstance(this),ids);

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.

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() {

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)

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);

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)
})