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
There seems to be many issues with widgets since ages. That said while searching a solution to one of them, I stumbled across this post: https://code.google.com/p/android/issues/detail?id=2539#c15
Basically the idea is to remove the app configuration activity from the manifest and check during onUpdate if the widget has been configured, if not open the configuration activity.
It's entirely transparent to the user and is said to fix the "add/zombie widget" issue. Will try that now.
However it doesn't solve the issue with removed widgets being updated upon reboot, even though it seems to have been fixed in recent Android versions (4.4+ not sure which one?).
On older versions of Android, I observed that all widgets I've manually removed from the launcher transforms into zombies upon rebooting, the OS effectively calling onUpdate for each of those widgets, hence I had to keep a list of deleted widget.
Now deleted widget IDs are actually reused for new widgets, so I have to stop tracking deleted widgets. Sadly I have no clue when (which Android version) this issue was fixed and IDs started to get re-used.
I solved this problem like this,
in the widget provider's onUpdate() method I check if the widget was configured, and if it wasn't I don't do anything, so no ghost widgets. At the end of the configuration I just set it to true and I'm good to go. Just don't forget to remove it from sharedpreference when the widget is deleted.
@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);
}
}
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"
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