Подтвердить что ты не робот

Виджет не удаляется при передаче RESULT_CANCELED в качестве результата для активности конфигурации

У меня есть некоторые проблемы с моими виджетами. Вот описание:

Контекст:

У меня есть домашний виджет.

Когда я добавляю его, он выдает конфигурационную активность для установки некоторых параметров для виджета.

Если я назову setResult (RESULT_OK, resultValue);, прежде чем завершить операцию настройки, виджет будет добавлен в Home.

Если я удалю виджет, перетащив его в корзину мусора, вызывается public void onDeleted (контекст контекста, int [] appWidgetIds) из моего класса AppWidgetProvider. Пока все хорошо.

Проблема: Если операция конфигурации завершается с помощью результирующего кода RESULT_CANCELED (setResult (RESULT_CANCELED);), public void onDeleted (контекст контекста, int [] appWidgetIds) из моего класса AppWidgetProvider не вызывается и виджет остается в списке активных виджетов. Когда я перезапускаю телефон, вызывается onUpdate (контекст контекста, AppWidgetManager appWidgetManager, int [] appWidgetIds) из моего класса AppWidgetProvider и в int [] appWidgetIds у меня есть все виджеты (ids), которые должны быть отменены (удалены до добавления) + активные (те, которые фактически отображаются в Доме). Виджеты, которые были удалены путем перетаскивания в корзину мусора, не отображаются в этом списке. Со временем этот список идентификаторов виджетов продолжает становиться все больше и больше, если пользователь отменяет конфигурацию Activity.

В справочнике API говорится примерно так: "Если вы вернете RESULT_OK с помощью Activity.setResult(), AppWidget будет добавлен, и вы получите ACTION_APPWIDGET_UPDATE для этого AppWidget. Если вы вернете RESULT_CANCELED, хост отменит добавление и не отобразит этот AppWidget, и вы получите ACTION_APPWIDGET_DELETED."

Может ли кто-нибудь дать мне несколько намеков на это? Спасибо.

Вот мой манифест:

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

Остальная часть кода не имеет значения, поскольку она была описана выше (и у меня нет разрешения на ее публикацию).

4b9b3361

Ответ 1

У меня была эта же проблема, я сделал это на событии onPause

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

Проверьте идентификаторы виджета, виджет удален. Идентификатор хоста не важен, если у вас есть только один виджет приложения.

private boolean canceled = true;

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

В OK нажмите, я установил canceled false

Ответ 2

Вы уверены, что ваш код не имеет отношения к делу? Все в вашем манифесте выходит из книги и выглядит хорошо. Ваш код должен выглядеть очень похоже на это:

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

putExtra требуется, чтобы сообщить os, какой виджет вы не создаете... Для правильной работы необходимо закончить финиш. Если у вас его нет, вы не получите намерения, переданные операционной системе, и потеряете setResult.

Наконец, когда конфигурация не выходит из строя (back key, home key или bad code), создается виджет-призрак. Даже с совершенным кодом, если пользователь нажимает на домашний ключ во время настройки, у вас будет виджет, стоящий в очереди на систему, который на самом деле не существует на любом домашнем экране. Вот почему я называю их призраками. Как только виджет успешно завершит настройку, он будет вызывать onDeleted при удалении с главного экрана. У вас осталась проблема, что если призраки были созданы, onDisabled никогда не будет работать.

Последняя проверка. Поскольку выполняется config, в вашем файле info xml содержится следующее. Но на всякий случай это выглядит так:

    android:configure=your.package.name.ConfigurationActivity"

Ответ 3

Я решил эту проблему следующим образом:

в провайдере виджетов onUpdate() метод Я проверяю, был ли виджет настроен, и если это не так, я ничего не делаю, поэтому никаких виджонов-призрак. В конце конфигурации я просто установил его в true, и я готов идти. Просто не забудьте удалить его из sharedpreference, когда виджет будет удален.

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

    }


}

Ответ 4

Кажется, что с возрастом многие проблемы с виджетами. Тем не менее, при поиске решения одной из них, я наткнулся на этот пост: https://code.google.com/p/android/issues/detail?id=2539#c15

В основном идея состоит в том, чтобы удалить активность приложения из манифеста и проверить во время onUpdate, если виджет настроен, если не открыть активность конфигурации.

Он полностью прозрачен для пользователя и, как говорят, исправляет проблему "добавить/зомби". Попробуй это сейчас.


Однако он не решает проблему с удалением виджета, обновляемого при перезагрузке, хотя, похоже, он исправлен в последних версиях Android (4.4+ не уверен, какой из них?).

В старых версиях Android я заметил, что все виджеты, которые я вручную удалил из программы запуска, превращаются в зомби при перезагрузке, ОС эффективно вызывает onUpdate для каждого из этих виджетов, поэтому мне пришлось сохранить список удаленных виджета.

Теперь удаленные идентификаторы виджетов на самом деле повторно используются для новых виджетов, поэтому я должен прекратить отслеживать удаленные виджеты. К сожалению, я не знаю, когда (какая версия для Android) эта проблема была исправлена, а идентификаторы начали повторно использоваться.