Динамическое включение или отключение виджета не работает - PullRequest
15 голосов
/ 06 февраля 2010

Мы хотели бы включить или отключить виджеты с помощью кода. Когда мы говорим «отключить» мы подразумеваем, что виджет, который зарегистрирован в приложении не должен отображаться в списке доступных пользователю виджетов при они пытаются добавить виджет на главный экран. Этот вопрос задавался, к сожалению, много раз без ответ.

Был один ответ Дайан Хэкборн на отдельный вопрос виджета, который предполагает, что можно было использовать Диспетчер пакетов для отключения виджетов:

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

Это, однако, не работает. Компонент виджета все равно будет отображаться в списке виджетов. Может случиться так, что AppWidgetService (расположен в Base.git источника Android на \ src \ base \ services \ java \ com \ android \ server), который загружает список доступных виджетов, кэширует этот список из доступных виджетов. Если бы это было так, то выше код, который включает или отключает компонент виджета, будет работать после сброс устройства, потому что не было бы кеша; Это не.

Я также попытался изучить некоторые методы AppWidgetProvider, например, отфильтровывая любые события. Я не думаю это пойдет куда угодно, потому что AppWidgetService, который заполняет список, использует диспетчер пакетов, чтобы найти все компоненты, которые ловят действие ACTION_APPWIDGET_UPDATE при запуске и когда пакет добавлено (т.е. установлено новое приложение). Единственный раз, когда провайдер удалено из этого списка в трансляции ACTION_PACKAGE_REMOVED. Таким образом, учитывая, что поставщики всегда будут там, независимо от включено / отключено состояние компонента, я посмотрел на фактическое список действий, который отображается из приложения Launcher, когда пользователь долго щелкает рабочий стол и добавляет виджет: AppWidgetPickActivity в Settings.GIT в com.android.settings. Это, к сожалению, заполняет список непосредственно из AppWidgetService, без какой-либо фильтрации Статус компонента включен: void putInstalledAppWidgets (элементы списка) { Список установлен = mAppWidgetManager.getInstalledProviders (); putAppWidgetItems (установлено, пусто, элементы); }

Я бы хотел посмотреть, преодолел ли кто-нибудь это препятствие. Возможно я идти по этому пути неправильно. Все, что я хочу, это иметь возможность удалить виджет из списка виджетов, доступных пользователю при попытке добавить виджет на их домашний экран.

Ответы [ 3 ]

4 голосов
/ 06 февраля 2010

Возможно, что AppWidgetService (находится в источнике Android Base.git на \ SRC \ база \ услуги \ Java \ COM \ андроида \ сервер), который загружает список доступные виджеты, кеширует этот список доступные виджеты.

Да, насколько я могу судить. Сохраняет список в mInstalledProviders; этот список добавляется через readStateFromFileLocked(), который вызывается из логики запуска системы.

Если бы это было так, тогда приведенный выше код, который позволяет или отключает компонент виджета будет работать после сброса устройства, потому что не было бы кеша; это не так.

Вы предполагаете, что кэш RAM. Кеш - это файл XML.

Это, к сожалению, заполняет список прямо из AppWidgetService, без каких-либо фильтрация для компонента включена статус

И это может показаться ошибкой в ​​Android. В более общем смысле, я думаю, что вся проблема с кэшированием - это ошибка - я не вижу способа восстановить, если этот кэш выйдет из синхронизации.

Я бы порекомендовал опубликовать рецензию в качестве проблемы на общедоступном трекере проблем Android , если вы этого еще не сделали.

3 голосов
/ 11 марта 2014

у меня сработало! Мне пришлось использовать DONT_KILL_APP, иначе это немедленно убило бы мое приложение. Кроме того, мне пришлось закомментировать условие, чтобы проверить, было ли оно уже в том же состоянии.

Вот вспомогательный метод, который я создал:

public void setMyCustomWidgetEnabled( boolean bEnable )
    {
        Log.d( LOG_TAG_NAME, "Entering setMyCustomWidgetEnabled( " + bEnable + " )..." );

        PackageManager rPackageManager = getPackageManager();
        if( rPackageManager != null )
        {
            ComponentName rComponentName = new ComponentName( getBaseContext(), MyCustomWidget.class );

            int nComponentEnabledState = rPackageManager.getComponentEnabledSetting( rComponentName );

            if( bEnable )
            {
                //if( nComponentEnabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED )
                {
                    // Change the State to Enabled
                    rPackageManager.setComponentEnabledSetting( rComponentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP );

                    Log.d( LOG_TAG_NAME, "-> Changed My Custom Widget' to ENABLED!" );
                }
            }
            else
            {
                //if( nComponentEnabledState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED )
                {
                    // Change the State to Disabled
                    rPackageManager.setComponentEnabledSetting( rComponentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP );

                    Log.d( LOG_TAG_NAME, "-> Changed 'My Custom Widget' to DISABLED!" );
                }
            }
        }

        Log.d( LOG_TAG_NAME, "Leaving setMyCustomWidgetEnabled( " + bEnable + " )..." );
}
0 голосов
/ 09 января 2012

Функция

pm.setComponentEnabledSetting()

работает в ICS. Когда виджет отключен, он удаляется из списка доступных виджетов. Небольшое утешение на данный момент, но это по крайней мере исправлено

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...