通过程序从活动/服务/接收器更新小部件。

109

我知道这是可能的,但我无法想出一种从主活动触发我的小部件更新的方法。难道没有可以广播的通用意图吗?

10个回答

217

如果你正在使用AppWidgetProvider,你可以通过以下方式更新:

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

30
你在哪里设置 widgetId - Kris B
38
通过以下方式获取数组:int ids[] = AppWidgetManager.getInstance(getApplication()).getAppWidgetIds(new ComponentName(getApplication(), WidgetProvider.class)); - MobileMon
11
你可以使用常量,无需硬编码:intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE); - Mārtiņš Briedis
3
不要按照 @gelupa 的评论中使用 R.xml.mywidget 作为小部件 ID!这是完全错误的,让我浪费了4个小时来调试!!!请使用 MobileMon 的解决方案获取正确的小部件ID。 - Ilja S.
5
对于ids:int widgetIDs[] = AppWidgetManager.getInstance(activity).getAppWidgetIds(new ComponentName(activity, widget.class));这段代码使用了Android中的AppWidgetManager类来获取指定widget类的实例,并获取它们的ID。获取到的ID会存储在一个整型数组widgetIDs中。 - abbasalim
显示剩余6条评论

81

当我搜索“如何从服务/操作更新小部件”时,这很有帮助(但可能可以从任何上下文中实现):

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

我知道我来晚了大约6个月。但是我同意Andrew的观点。我尝试了这个帖子中的原始方法。有些关于抓取ID的问题导致它开始出错。这种直接手动更新字段的方法效果更好,至少对于我的目的来说。 - durbnpoisn
厉害的东西。不知道你是怎么做到的,但对于我小部件的所有实例来说都运行得很好,非常顺畅。 :) - Atul O Holic
这对我也起作用了。我以为我们需要进行广播和onReceive,但我的要求与此完美契合。 - stingray_

34

所以要从活动中更新小部件,您可以这样做:

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

对我来说有效 :)


它调用了onReceive重写方法。但我想知道如何调用onUpdate方法。 - Amit Thaper

28

试一下这个:

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

2
令人惊奇的是,仅仅这个小小的答案就解决了问题。虽然我仍不知道实例化Widget类和直接调用onUpdate方法的影响,但好在它最终成功了 :) - Henrique de Sousa
1
谢谢。我正在测试它,将会发布反馈。已经测试并确认可用。不过我在想,如果有不同类型的小部件,它是否能够正常工作?(顺便加一分,因为它能够工作) - Si8
我总是得到ID为0。 - user6264840
这在Android Oreo上不起作用,有什么解决方法吗? - stuckedoverflow

15

如果你正在使用像ListView、GridView或StackView这样使用集合的小部件来更新小部件的项,请按照以下步骤进行操作:

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

通过使用方法notifyAppWidgetViewDataChanged(),您可以强制小部件项实时获取任何新数据。


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

1
需要最低API级别为11。 - Anirudh Ramanathan
太棒了。你甚至不需要循环,有一个接受数组的notifyAppWidgetViewDataChanged()版本。 - Lawrence Kesteloot

6

Phaethon在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)

MyAppWidgetProvider是从AppWidgetProvider派生而来的:

MyAppWidgetProvider : AppWidgetProvider() {

5

如果您想以编程方式更新小部件,但没有直接访问YourWidgetProvider.class的权限,例如来自其他模块或库,则可以捕获YourWidgetProvider.class.getName()输出的内容并创建一个常量:

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

然后你就可以隐式地使用它:
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)

1

我的待办清单中的例子:

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

1

供参考,我在一个片段中需要这样做:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接