能否通过编程方式触发 APPWIDGET_UPDATE 的意图(Intent)?

9
我希望在我的小部件中添加一个按钮,以触发APPWIDGET_UPDATE意图并强制更新小部件类,但我没有在Intent中看到APPWIDGET_UPDATE作为静态字段。
这是否可能,并且如何实现?
Intent intent = new Intent(context, BaseWidgetProvider.class);
intent.setAction({APPWIDGET_UPDATE INTENT HERE})
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

views.setOnClickPendingIntent(R.id.MyWidgetButton, pendingIntent);
2个回答

16

可以。您将在AppWidgetManager中找到该操作:

intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE)

编辑:您需要提供要更新的小部件的ID。以下是完整示例:

AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
ComponentName widgetComponent = new ComponentName(context, YourWidget.class);
int[] widgetIds = widgetManager.getAppWidgetIds(widgetComponent);
Intent update = new Intent();
update.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds);
update.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
context.sendBroadcast(update);

谢谢。我在adb logcat中看到了意图触发,但小部件没有更新。我还需要做些什么吗?我的清单文件中已经有APPWIDGET_UPDATE作为意图过滤器了。 - NPike
onUpdate() 没有被调用?我需要回复你关于这个问题。 - Justin
您需要提供要更新的小部件的ID。如果您想要更新小部件的所有实例,可以从AppWidgetManager获取完整的ID列表(我已经编辑了我的评论以包括代码)。 - Justin
太好了!非常顺利,干得好!(除了在第三行将'appWidgetManager'更改为'widgetManager');) - Bobby
对我没有用...看起来在这种情况下仍然遵守了30分钟的最大更新频率? - swinefeaster
1
请注意,这可能会导致 https://dev59.com/0VPTa4cB1Zd3GeqPhC82#18534005我描述了一种替代方法来更新小部件以避免出现此问题。 - Guykun

2

我知道这是一个非常老的问题,但我认为这可能很有趣,因为Android更新了AppWidgets的刷新策略。我认为这个变化可能会防止现有的答案按预期工作。

这是我的解决方案,使用RemoteViews和集合。

public static final String ACTION_WIDGET_UPDATE = "com.yourpackage.widget.ACTION_UPDATE";

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(ACTION_WIDGET_UPDATE)) {
        int widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
        AppWidgetManager.getInstance(context)
                .notifyAppWidgetViewDataChanged(widgetId, R.id.widgetColectionRoot);
    }
    super.onReceive(context, intent);
}

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                     int[] appWidgetIds) {
    super.onUpdate(context, appWidgetManager, appWidgetIds);
    for (int widgetId : appWidgetIds) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            RemoteViews collectionRemoteView = getRemoteViews(widgetId, context);
            appWidgetManager.updateAppWidget(widgetId, collectionRemoteView);
        }

    }
}

@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@SuppressWarnings("deprecation")
private RemoteViews getRemoteViews(int widgetId, Context context) {
    // Sets up the intent that points to the RemoteViewService
    // that will
    // provide the views for this collection.
    Intent widgetUpdateServiceIntent = new Intent(context,
            RemoteViewsService.class);
    widgetUpdateServiceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
    // When intents are compared, the extras are ignored, so we need
    // to embed the extras
    // into the data so that the extras will not be ignored.
    widgetUpdateServiceIntent.setData(
            Uri.parse(widgetUpdateServiceIntent.toUri(Intent.URI_INTENT_SCHEME)));
    RemoteViews collectionRemoteView = new RemoteViews(context.getPackageName(),
            R.layout.widget_collection);
    collectionRemoteView.setRemoteAdapter(widgetId,
            R.id.widgetColectionRoot, widgetUpdateServiceIntent);

    collectionRemoteView.setEmptyView(R.id.widgetColectionRoot, R.id.widgetEmpty);

    // This section makes it possible for items to have
    // individualized behavior.
    // It does this by setting up a pending intent template.
    // Individuals items of a collection
    // cannot set up their own pending intents. Instead, the
    // collection as a whole sets
    // up a pending intent template, and the individual items set a
    // fillInIntent
    // to create unique behavior on an item-by-item basis.
    Intent selectItemIntent = new Intent(context,
            BrochuresWidgetProvider.class);

    Intent refreshIntent = new Intent(selectItemIntent);
    refreshIntent.setAction(ACTION_WIDGET_UPDATE);
    PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(
            context, 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    collectionRemoteView.setOnClickPendingIntent(R.id.widgetReload,
            refreshPendingIntent);
    return collectionRemoteView;
}

当然,您还需要在小部件提供程序声明中的清单上注册该意图过滤器。

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