作为配置活动的结果传递RESULT_CANCELED时,小部件不会被删除

时间:2010-12-08 22:47:26

标签: android android-widget

我的小部件有些问题。这是描述:

上下文

我有一个家庭小部件。

当我添加它时,它会弹出一个配置活动,为窗口小部件设置一些参数。

如果在完成配置活动之前调用 setResult(RESULT_OK,resultValue); ,则窗口小部件将添加到主页。

如果我通过将小部件拖到垃圾箱来删除小部件,则会调用来自我的AppWidgetProvider类的 public void onDeleted(Context context,int [] appWidgetIds)。 到目前为止一切都很好。

问题: 如果配置Activity以结果代码RESULT_CANCELED( setResult(RESULT_CANCELED); )退出,则不会调用来自AppWidgetProvider类的 public void onDeleted(Context context,int [] appWidgetIds)并且窗口小部件保留在活动窗口小部件列表中。当我重新启动手机时,调用来自我的AppWidgetProvider类的 onUpdate(上下文上下文,AppWidgetManager appWidgetManager,int [] appWidgetIds),并且在int [] appWidgetIds中我有所有应该是的小部件(ids)取消(在添加之前删除)+活动的(在Home上实际显示的那些)。通过拖动到垃圾箱删除的窗口小部件不会显示在此列表中。随着时间的推移,如果用户从配置活动中取消,则此小部件ID列表会越来越大。

API参考说明如下: “如果使用Activity.setResult()返回RESULT_OK,将添加AppWidget,您将收到此AppWidget的ACTION_APPWIDGET_UPDATE广播。如果您返回RESULT_CANCELED,主机将取消添加而不显示此AppWidget,您将收到一个ACTION_APPWIDGET_DELETED广播。“

有人能给我一些暗示吗? 谢谢。

这是我的清单:

<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
    <receiver android:name=".MytWidget" android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data android:name="android.appwidget.provider"
                    android:resource="@xml/my_widget_provider" />
    </receiver>
    <activity android:name=".ConfigurationActivity">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
        </intent-filter>
    </activity>
</application>

其余代码不相关,因为上面已经解释过(我无权发布)。

4 个答案:

答案 0 :(得分:13)

我有同样的问题,我在onPause事件

上做了这个
public void removeWidget(int appWidgetId) {
    AppWidgetHost host = new AppWidgetHost(Config.this, 1);
    host.deleteAppWidgetId(appWidgetId);
}

检查小部件ID,删除小部件。 如果您只有一个应用小部件主机,则主机ID并不重要。

private boolean canceled = true;

@Override
protected void onPause() {
    if(canceled) {
        removeWidget(appWidgetId);
    }
    super.onPause();
}

在确定点击中,我设置了canceled false

答案 1 :(得分:8)

您确定您的代码不相关吗?你的清单中的所有东西都不在书中,看起来很好。您的代码应该与此非常相似:

    public void configCancelOnClick(View v) {
    MyLog.d(TAG, "configCancelOnClick");
    Intent intent = new Intent();
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    setResult(RESULT_CANCELED, intent);
    finish();
}

putExtra需要告诉操作系统你没有创建哪个小部件...... 完成需要正确关闭。如果你没有它,你将无法正确传递给操作系统的意图并丢失setResult。

最后,当config未正确退出(后退键,主页键或错误代码)时,会创建一个ghost小部件。即使使用完美的代码,如果用户在配置中点击主页键,您将有一个排队到系统的小部件,这个小部件在任何主屏幕上都不存在。这就是我称之为幽灵的原因。一旦窗口小部件成功完成配置,它将在从主屏幕移除时调用onDeleted。你留下的问题是,如果创建了鬼魂,onDisabled将永远不会运行。

最后一次检查。自配置运行以来,您的info xml文件中包含以下内容。但为了以防万一,它看起来像这样:

    android:configure=your.package.name.ConfigurationActivity"

答案 2 :(得分:0)

我解决了这个问题,

在小部件提供程序的onUpdate()方法中,我检查小部件是否已配置,如果不是,我不做任何事情,所以没有鬼小部件。在配置结束时,我将其设置为true,我很高兴。删除小部件时,不要忘记将其从共享首选项中删除。

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

    for(final int appWidgetId : appWidgetIds)
    {
        final StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(appWidgetId);
        stringBuilder.append("_conf");
        if(context.getSharedPreferences("settings",0).getBoolean(stringBuilder.toString(),false)) 
            updateAppWidget(context,appWidgetId,appWidgetManager);

    }


}

答案 3 :(得分:0)

自从多年以来,小部件似乎存在许多问题。也就是说,在搜索其中一个解决方案时,我偶然发现了这篇文章:https://code.google.com/p/android/issues/detail?id=2539#c15

基本上,我们的想法是从清单中删除应用配置活动,并在onUpdate期间检查是否已配置窗口小部件,如果未打开配置活动。

它对用户完全透明,据说可以修复“添加/僵尸小部件”问题。现在就试试吧。


然而,它并没有解决重新启动后删除的小部件被更新的问题,即使它似乎已在最近的Android版本中修复(4.4+不确定哪个?)。

在旧版本的Android上,我观察到我从启动器中手动删除的所有小部件在重新启动时都会转换为僵尸,操作系统会为每个小部件有效地调用onUpdate,因此我必须保留已删除小部件的列表。

现在已删除的窗口小部件ID实际上已用于新窗口小部件,因此我必须停止跟踪已删除的窗口小部件。可悲的是,我不知道什么(Android版本)修复了这个问题并且ID开始被重复使用。