Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Widget not deleted when passing RESULT_CANCELED as result for configuration activity

I have some problems with my widgets. Here is the description:

Context:

I have a home widget.

When I add it, it pops a configuration Activity for setting some parameters for the widget.

If I call setResult(RESULT_OK, resultValue); before finishing the configuration Activity, the widget is added to the Home.

If I delete the widget by dragging it to the trash bin, public void onDeleted(Context context, int[] appWidgetIds) from my AppWidgetProvider class gets called. So far so good.

Problem: If the configuration Activity exits with result code RESULT_CANCELED (setResult(RESULT_CANCELED);), public void onDeleted(Context context, int[] appWidgetIds) from my AppWidgetProvider class is not called and the widget remains in the active widgets list. When I restart the phone, onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) from my AppWidgetProvider class is called and in int[] appWidgetIds I have all widgets (the ids) that supposed to be canceled (deleted before being added) + the active ones (the ones that are actually displayed on Home). The Widgets that were deleted by dragging to the trash bin are not displayed in this list. With time this list of widgets ids keeps getting bigger and bigger if the user is canceling from the configuration Activity.

The API reference says something like: "If you return RESULT_OK using Activity.setResult(), the AppWidget will be added, and you will receive an ACTION_APPWIDGET_UPDATE broadcast for this AppWidget. If you return RESULT_CANCELED, the host will cancel the add and not display this AppWidget, and you will receive a ACTION_APPWIDGET_DELETED broadcast."

Can anyone give me some hints on this? Thank you.

Here is my manifest:

<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>

The rest of the code is not relevant since it was explained above (and I don't have permission to post it).

like image 300
Flav Avatar asked Dec 08 '10 22:12

Flav


2 Answers

I had this same problem, i did this on the onPause event

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

Checked the widget ids, the widget is removed. The host id is not important if you only have one app widget host.

private boolean canceled = true;

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

In the OK click, i set the canceled false

like image 141
tsukimi Avatar answered Nov 10 '22 19:11

tsukimi


Are you sure your code isn't relevant? Everything in your manifest is out of the book and looks good. Your code should look very similar to this:

    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();
}

The putExtra is required to tell the os which widget you are not creating... The finish is required to shut down correctly. If you don't have it, you won't get the intent passed to the operating system correctly and lose the setResult.

Finally, when config doesn't exit correctly (back key, home key, or bad code), a ghost widget is created. Even with perfect code, if the user hits the home key while in config, you will have a widget queued to the system that does not really exist on any home screen. That's why I call them ghosts. Once a widget has successfully completed config, it will invoke onDeleted when removed from the home screen. You are left with the problem that, if ghosts have been created, onDisabled will never, ever, run.

One last check. Since config runs, you have the following in your info xml file. But just in case, it looks like this:

    android:configure=your.package.name.ConfigurationActivity"
like image 38
Howard Hodson Avatar answered Nov 10 '22 20:11

Howard Hodson