tags:

views:

232

answers:

1

We would like to enable or disable widgets via code. When we say "disable" we mean that a widget which is registered in an application should not show up in the list of widgets available to the user when they try to add a widget to their home screen. This question has been asked, unfortunately, many times without answer.

There was one response by Dianne Hackborn to a separate widget question which suggested that it was possible to use the package manager to disable widgets:

PackageManager pm = context.getPackageManager(); pm.setComponentEnabledSetting(new ComponentName( "com.example.android.apis", ".appwidget.ExampleBroadcastReceiver"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, // or DISABLED PackageManager.DONT_KILL_APP);

This, however, does not work. The widget component will still appear in the list of widgets. It may be that the AppWidgetService (located in the Android source's Base.git at \src\base\services\java\com\android \server), which loads the list of available widgets, caches this list of available widgets. If that were the case, though, then the above code which enables or disables the widget component would work after a device reset because there would be no cache; it does not.

I have also tried looking into overriding some methods of the AppWidgetProvider, such as filtering out any events. I don't think this will go anywhere, because the AppWidgetService, which populates the list, uses the Package Manager to find all components which catch the ACTION_APPWIDGET_UPDATE action on startup and when a package is added (i.e. a new app is installed). The only time that a provider is removed from this list is on a ACTION_PACKAGE_REMOVED broadcast. So given that the providers will always be there, regardless of the enabled/disabled state of the component, I have looked into the actual list activity which is shown from the Launcher app when the user long- clicks the desktop and adds a widget: AppWidgetPickActivity in Settings.GIT in com.android.settings. This, unfortunately, populates the list directly from the AppWidgetService, without any filtering for the component's enabled status: void putInstalledAppWidgets(List items) { List installed = mAppWidgetManager.getInstalledProviders(); putAppWidgetItems(installed, null, items); }

I would love to see if anyone has overcome this hurdle. Perhaps I am going about it the wrong way. All I want is to be able to remove a widget from the list of widgets available to the user when they try to add a widget to their home screen.

+1  A: 

It may be that the AppWidgetService (located in the Android source's Base.git at \src\base\services\java\com\android \server), which loads the list of available widgets, caches this list of available widgets.

It does, near as I can tell. It stores the list in mInstalledProviders; this list is added to via readStateFromFileLocked(), which appears to be called from the system startup logic.

If that were the case, though, then the above code which enables or disables the widget component would work after a device reset because there would be no cache; it does not.

You assume a RAM cache. The cache is an XML file.

This, unfortunately, populates the list directly from the AppWidgetService, without any filtering for the component's enabled status

And this would appear to be a bug in Android. More generally, the whole caching thing I would think is the bug -- I see no way to recover if that cache gets out of sync.

I would recommend you post your writeup as an issue on the public Android issue tracker, if you have not done so already.

CommonsWare