Android:如何强制更新特定类型的所有小部件 [英] Android: How do I force the update of all widgets of a particular kind

查看:13
本文介绍了Android:如何强制更新特定类型的所有小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到很多类似的问题,而且我一遍又一遍地看到相同的答案.我不想为我的应用拥有的每一种小部件都提供一个服务,尤其是看到我的应用已经有 2 个持久服务.

I have seen many questions along these lines, and I keep seeing the same answer over and over. I don't want to have to have a Service for every kind of widget my app has, especially seeing as my app already has 2 persistent services.

具体来说,如果我的现有服务之一发现数据已更改,我想更新我的小部件.在计时器上执行此操作很烦人,因为更新之间可能需要几天时间,或者一小时内可能会有好几次.我希望我的小部件始终显示最新信息.

Specifically, if one of my existing services sees that data has changed, I want to update my widgets. Doing this on a timer is annoying, as it could be days between updates or there might be several within one hour. I want my widgets to ALWAYS show up to date information.

Android 小部件设计似乎是在您的小部件在需要时提取信息的基础上工作的,我认为有许多明智的场景是活动可能希望将数据推送到小部件.

Android widget design seems to work on the basis that your widget pulls information when it wants it, I think there are many sensible scenarios where an activity may wish to push data to a widget.

阅读下面的答案,了解我如何准确地做到这一点.据我所知,如果处理得当,不会有任何不良影响.

Read the answer below for how I worked out how to do precisely this. As far as I can see there are no adverse effects if it is done properly.

推荐答案

要强制更新特定小部件提供程序的小部件,我们需要执行以下操作:

To force our widgets for a particular widget provider to be updated, we will need to do the following:

  • 设置我们的提供商以接收专门的广播
  • 发送专业广播:
  • Set up our provider to receive a specialized broadcast
  • Send the specialized broadcast with:
  1. 与提供者关联的所有当前小部件 ID
  2. 要发送的数据
  3. 只有我们的提供商才会响应的键(重要!)

  • 让我们的小部件在点击时更新(没有服务!)
  • 第 1 步 - 设置我们的 AppWidgetProvider

    我不会详细介绍如何创建 info xml 文件或更改 Android Manifest - 如果您不知道如何正确创建小部件,那么您应该先阅读大量教程.

    I will not go through the details of creating the info xml file or changes to the Android Manifest - if you don't know how to create a widget properly, then there are plenty of tutorials out there you should read first.

    这是一个示例 AppWidgetProvider 类:

    public class MyWidgetProvider extends AppWidgetProvider {
    
    public static final String WIDGET_IDS_KEY ="mywidgetproviderwidgetids";
    public static final String WIDGET_DATA_KEY ="mywidgetproviderwidgetdata";
    
    }
    
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.hasExtra(WIDGET_IDS_KEY)) {
            int[] ids = intent.getExtras().getIntArray(WIDGET_IDS_KEY);
            if (intent.hasExtra(WIDGET_DATA_KEY)) {
               Object data = intent.getExtras().getParcelable(WIDGET_DATA_KEY);
               this.update(context, AppWidgetManager.getInstance(context), ids, data);
            } else {
                this.onUpdate(context, AppWidgetManager.getInstance(context), ids);
            }
        } else super.onReceive(context, intent);
    }
    
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
        update(context, appWidgetManager, appWidgetIds, null);
    }
    
    //This is where we do the actual updating
    public void update(Context context, AppWidgetmanager manager, int[] ids, Object data) {
    
        //data will contain some predetermined data, but it may be null
       for (int widgetId : ids) {
            .
            .
            //Update Widget here
            .
            .
            manager.updateAppWidget(widgetId, remoteViews);
        }
    }
    

    第 2 步 - 发送广播

    在这里我们可以创建一个静态方法来更新我们的小部件.在小部件更新操作中使用我们自己的键很重要,如果我们使用 AppWidgetmanager.EXTRA_WIDGET_IDS,我们不仅会破坏我们自己的小部件,还会破坏其他小部件.

    Here we can create a static method that will get our widgets to update. It is important that we use our own keys with the widget update action, if we use AppWidgetmanager.EXTRA_WIDGET_IDS we will not only break our own widget, but others as well.

    public static void updateMyWidgets(Context context, Parcelable data) {
        AppWidgetManager man = AppWidgetManager.getInstance(context);
        int[] ids = man.getAppWidgetIds(
                new ComponentName(context,MyWidgetProvider.class));
        Intent updateIntent = new Intent();
        updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        updateIntent.putExtra(MyWidgetProvider.WIDGET_ID_KEY, ids);
        updateIntent.putExtra(MyWidgetProvider.WIDGET_DATA_KEY, data);
        context.sendBroadcast(updateIntent);
    }
    

    如果将此方法与多个提供商一起使用,请确保他们使用不同的密钥.否则,您可能会发现小部件 a 的代码正在更新小部件 b,这可能会产生一些奇怪的后果.

    If using this method with multiple providers MAKE SURE they use different keys. Otherwise you may find widget a's code updating widget b and that can have some bizarre consequences.

    第 3 步 - 点击更新

    另一件好事是让我们的小部件在被点击时神奇地更新.将以下代码添加到更新方法中以实现此目的:

    Another nice thing to do is to get our widget to update magiacally whenever it is clicked. Add the following code into the update method to acheive this:

    RemoteViews views = 
          new RemoteViews(context.getPackageName(),R.layout.mywidget_layout);
    
    Intent updateIntent = new Intent();
    updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
    updateIntent.putExtra(myWidgetProvider.WIDGET_IDS_KEY, ids);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
          context, 0, updateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    
    views.setOnClickPendingIntent(R.id.view_container, pendingIntent);
    

    此代码将导致在单击小部件时调用 onUpdate 方法.

    This code will cause the onUpdate method to be called whenever the widget is clicked on.

    备注

    • 对 updateWidgets() 的任何调用都会导致我们的小部件的所有实例都被更新.
    • 单击小部件将导致我们的小部件的所有实例被更新
    • 无需服务
    • 当然,请注意不要经常更新 - 小部件更新会消耗电池电量.
    • 请记住,所有小部件提供者都会收到广播,我们的特殊密钥可确保只有我们的小部件实际更新.

    这篇关于Android:如何强制更新特定类型的所有小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆