使用 appWidgetId 检查主屏幕上是不是存在小部件

Posted

技术标签:

【中文标题】使用 appWidgetId 检查主屏幕上是不是存在小部件【英文标题】:Check if a widget is exists on homescreen using appWidgetId使用 appWidgetId 检查主屏幕上是否存在小部件 【发布时间】:2013-06-27 13:18:02 【问题描述】:

我正在使用AlarmManager 来更新我的小部件。如果主屏幕上没有小部件,我想停止它。但是我在检测主屏幕上是否没有小部件时遇到了问题。

每当我尝试使用这种方式获取 AppWidgetIds 时:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

int[] appWidgetIDs = appWidgetManager
    .getAppWidgetIds(new ComponentName(context, Widget.class));

我得到appWidgetIDs 的长度,而实际上主屏幕上没有小部件。 为什么?

因此,我想知道是否有办法检测主屏幕上是否存在小部件 ID。

谢谢你。

【问题讨论】:

【参考方案1】:

恭喜,您遇到了幻像应用小部件。它似乎记录在android issue tracker 上。它们通常发生在应用小部件的配置活动被取消时,尽管这似乎是由于配置活动的不当实施所致;在将活动结果设置为RESULT_CANCELED 时,开发人员忽略了将 appwidget ID 作为额外包含在内。 (甚至 Google 的 ApiDemos 示例应用程序都忽略了这样做!)

正确的实现是这样的:

public class AppWidgetConfigActivity extends Activity 

    private int appWidgetId;
    private Intent resultValue;

    protected void onCreate(bundle saved) 
        super.onCreate(saved);

        // get the appwidget id from the intent
        Intent intent = getIntent();
        appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);

        // make the result intent and set the result to canceled
        resultValue = new Intent();
        resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        setResult(RESULT_CANCELED, resultValue);

        // if we weren't started properly, finish here
        if (appwidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) 
            finish();
        

        /* ... */
    

    /* ... */

    private void finishConfigure() 
        /* finish configuring appwidget ... */
        setResult(RESULT_OK, resultValue);
    

到目前为止,我不知道如果不自己记账,就无法检测到幻影应用小部件的存在。我建议存储一个表示配置活动未取消的 SharedPreferences 值,然后在您的其他代码中查询该值。如果您遇到一个幻像小部件,您还可以使用此信息“删除”一个幻像小部件。在您的 appwidget 配置活动中:

private void finishConfigure() 
    /* finish configuring appwidget ... */
    setResult(RESULT_OK, resultValue);

    String key = String.format("appwidget%d_configured", appwidgetId);
    SharedPreferences prefs = getSharedPreferences("widget_prefs", 0);
    prefs.edit().putBoolean(key, true).commit;

然后您可以检查您是否至少有一个非幻像应用小部件,如下所示:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
AppWidgetHost appWidgetHost = new AppWidgetHost(context, 1); // for removing phantoms
SharedPreferences prefs = getSharedPreferences("widget_prefs", 0);
boolean hasWidget = false;

int[] appWidgetIDs = appWidgetManager.getAppWidgetIds(new ComponentName(context, Widget.class));
for (int i = 0; i < appWidgetIDs.length; i++) 
    int id = appWidgetIDs[i];
    String key = String.format("appwidget%d_configured", id);
    if (prefs.getBoolean(key, false)) 
        hasWidget = true;
     else 
        // delete the phantom appwidget
        appWidgetHost.deleteAppWidgetId(id);
    


if (hasWidget) 
    // proceed
 else 
    // turn off alarms

【讨论】:

这个答案值得更多的赞誉!我相信很多人都会遇到这个问题(即使他们不知道),因为您从 Android Studio 获得的示例“hello world”appwidget 代码没有正确执行,这就是很多的人将开始。根据您的建议,在将活动结果设置为 RESULT_CANCELED 时将 appwidget ID 作为额外包含在内,我似乎不再创建任何幻像小部件。谢谢! 至于删除幻像部件的代码应该无论出于何种原因出现,您建议将其放在哪里?不在onUpdate() 中,因为这似乎是在首次打开配置活动时调用的,这是在配置小部件之前 - 不想在小部件诞生之前杀死它! 非常有帮助且写得很好的答案。谢谢。 你在哪里调用finishConfigure?

以上是关于使用 appWidgetId 检查主屏幕上是不是存在小部件的主要内容,如果未能解决你的问题,请参考以下文章

检查用户是不是已经在 Chrome 的主屏幕上安装了 PWA?

无法使用react-native app中的redux-persist检查索引/主文件上是否已加载持久状态

如何检查元素是不是在屏幕上完全可见?

Android:将 AppWidgetId 传递给服务

如何从文本框(windows窗体)检查主键是不是存在于我的数据库中,c#

使用流在 Flutter 中不起作用检查身份验证状态