Check if widget exists on desktop using appWidgetId

I use AlarmManager to update my widgets. And I want to stop it if there is no widget on the desktop. But I had a problem with detecting the absence of a widget on the main screen.

As always, when I try to use AppWidgetId using this method:

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

I get the length of appWidgetIDs while there is no widget on the main screen. Why?

So I would like to know if there is a way to detect that there is a widget id on the home screen.

Thanks in advance.

+7
source share
1 answer

Congratulations, you are facing phantom appwidgets. It appears to be documented in tracking Android issues . Usually they occur when the configuration activity for the application is visibly canceled, although this seems to be due to the incorrect implementation of the configuration activity; developers neglect to add the appwidget identifier as an additional identifier when setting the result of an operation to RESULT_CANCELED . (even the Google ApiDemos sample application neglects this!)

The correct implementation is as follows:

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

So far, I do not know how to detect the presence of a phantom appwidget without your own accounting statements. I suggest storing a SharedPreferences value indicating that the configuration activity has not been canceled, and then request that value in your other code. You can also use this information to โ€œuninstallโ€ the phantom widget if you encounter it. In your appwidget configuration configuration:

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

You can then verify that you have at least one non-w603 appwidget:

 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 } 
+16
source

All Articles