AppWidgetProvider:在小部件放置时未调用 onAppWidgetOptionsChanged

Posted

技术标签:

【中文标题】AppWidgetProvider:在小部件放置时未调用 onAppWidgetOptionsChanged【英文标题】:AppWidgetProvider: onAppWidgetOptionsChanged not being called on widget placement 【发布时间】:2013-09-02 19:42:15 【问题描述】:

根据 AppWidgetProvider 中关于 onAppWidgetOptionsChanged 的​​文档: “在第一次放置小部件时以及在任何时候调整小部件的大小时都会调用它。”

但是,当我将小部件放在 android 4.2 和 4.3 的股票启动器上时,不会立即调用此方法(仅在我调整小部件大小后)。我在自己的应用程序以及 CommonsWare 的 https://github.com/commonsguy/cw-omnibus/tree/master/AppWidget/Resize

上尝试过

我有什么遗漏吗?

编辑:我发现唯一能使该方法正常工作的启动器(如 Google 文档所述)是 Action Launcher Pro;干得好,谢谢,克里斯·莱西!为什么股票启动器不起作用?其他人有这个问题吗?

【问题讨论】:

这曾经有效。不过,我可以在 4.3 模拟器和 Galaxy Nexus 上重现您的问题。我将不得不进行更多实验并回复您。感谢您指出这一点! @CommonsWare 检查我的解决方法答案。 【参考方案1】:

感谢您关注此问题。我将更新 Android 文档以反映这一点。

但是,我们建议不要在 onUpdate() 中强制调用 onAppWidgetOptionsChanged(),而是推荐如下方法:

public class AppWidget extends AppWidgetProvider 

    .... 

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) 

super.onUpdate(context, appWidgetManager, appWidgetIds);

final int N = appWidgetIds.length;
for (int i=0; i<N; i++) 
            int appWidgetId = appWidgetIds[i];
            Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
            updateWidget(context, appWidgetManager, appWidgetId, options);
        




public void onAppWidgetOptionsChanged (Context context, AppWidgetManager 
        appWidgetManager, int appWidgetId, Bundle newOptions) 

    updateWidget(context, appWidgetManager, appWidgetId, newOptions);


private void updateWidget(Context context, AppWidgetManager appWidgetManager,

        int appWidgetId, Bundle options) 

    // Do whatever you need to do to the widget. Include any customization based
    // on the size, included in the options. Be sure to have a graceful fallback if
    // no valid size data is included in the bundle.


    

    ...

【讨论】:

很遗憾appWidgetManager.getAppWidgetOptions 需要 API 级别 16! 那么appWidgetManager.getAppWidgetOptions 在以前的级别(&lt;16) 中被忽略还是通过异常忽略?【参考方案2】:

因此,文档中提到了 onUpdate():“...[I]如果您已声明配置 Activity,则在用户添加 App Widget 时不会调用此方法,但会在后续更新时调用此方法。” 好吧,显然这也不是真的。 onUpdate() 被调用,即使我的小部件有一个配置活动。

无论如何,从 onUpdate() 调用 onAppWidgetOptionsChanged() 似乎是基于 4.2+ 的启动器中的一种解决方法,因为当小部件首次放置在主屏幕上时会调用 onUpdate(),我们可以从AppWidgetManager 实例。

@Override
  public void onUpdate(Context context, AppWidgetManager appWidgetManager, int appWidgetIds[])
      super.onUpdate(context, appWidgetManager, appWidgetIds);
      final int N = appWidgetIds.length;
      for (int i=0; i<N; i++) 
          int appWidgetId = appWidgetIds[i];
          Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId);
          if(options!=null)
              int nwidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
              int nheight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
              onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, options);
          
      
  

【讨论】:

同意,这可能是最好的选择,假设这是新的正确(尽管未记录)行为。建议对您的代码进行两个调整:使用for (appWidgetId : appWidgetIds),并且您不需要检索nwidthnheight,因为您不在这里使用它们。研究工作做得很好! 顺便说一句,我为文档错误提交了一个问题,因为我假设这是正确的行为:code.google.com/p/android/issues/detail?id=59623

以上是关于AppWidgetProvider:在小部件放置时未调用 onAppWidgetOptionsChanged的主要内容,如果未能解决你的问题,请参考以下文章

Check Widget放置在Android屏幕上

在 AppWidgetProvider 中执行 UnregisterReceiver() 时出错

如何在android编程中获取放置在小部件上的textview文本

在从 AppWidgetProvider 调用的异步任务中将字符串分配给文本值

AppWidgetProvider - 每次对任何 AppWidget 文件进行更改时都会触发 onUpdate 吗?

在小部件上插入临时图像[关闭]