Android AppWidget onClick не работает после сборки мусора

Я создал AppWidget для своего приложения и установил для updatePeriodMillis значение 0, потому что этот виджет ничего не делает, если пользователь не взаимодействует.

Все работает нормально, пока андроид не почистит оперативку. Затем виджет больше не будет отвечать до тех пор, пока приложение не будет запущено снова или устройство не будет перезагружено (в обоих случаях onUpdate() снова запустится).

Итак, мой вопрос: что мне нужно сделать, чтобы вернуть его к работе после того, как Android выгнал приложение?

Это часть манифеста:

    <receiver android:name="WidgetProvider" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="PATH.widgetBtnStartClicked" />
        </intent-filter>
        <meta-data android:name="android.appwidget.provider"
                   android:resource="@xml/appwidget_provider_info" />
    </receiver>

Это часть моего WidgetProvider:

public class WidgetProvider extends AppWidgetProvider {

private static final String BTN_START_CLICKED = "PATH.widgetBtnStartClicked";


private static Values values;

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {

    super.onUpdate(context, appWidgetManager, appWidgetIds);

    // get RemoteView (widget):
    for (int i = 0; i < appWidgetIds.length; i++) {
        int appWidgetId = appWidgetIds[i];

        RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.appwidget);


        // Register onClick for App-start-button:
        Intent intentLaunch = new Intent(BTN_APP_LAUNCH_CLICKED);
        intentLaunch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntentLaunch = PendingIntent.getBroadcast(
                context, appWidgetId, intentLaunch,
                PendingIntent.FLAG_UPDATE_CURRENT);
        views.setOnClickPendingIntent(R.id.appwidget_btn_launch,
                pendingIntentLaunch);


        appWidgetManager.updateAppWidget(appWidgetId, views);

    }

}

@Override
public void onReceive(Context context, Intent intent) {
    RemoteViews views = new RemoteViews(context.getPackageName(),
            R.layout.appwidget);

    super.onReceive(context, intent);

    AppWidgetManager appWidgetManager = AppWidgetManager
            .getInstance(context);
    ComponentName componentName = new ComponentName(context,
            WidgetProvider.class);

    if (intent.getAction().equals(BTN_APP_LAUNCH_CLICKED)) {

        //do some stuff..
    }
    // update views
    appWidgetManager.updateAppWidget(componentName, views);

}

Я надеюсь, что есть все, что вам нужно, чтобы понять проблему. Просто скажи мне, если нет!


person Klumbe    schedule 30.10.2013    source источник


Ответы (1)


Я думаю, что ваше приложение использует только onUpdate() для обновления виджета. Существуют и другие события, которые приводят к тому, что ожидающие намерения «отбрасывают» виджет. Например, упомянутая вами очистка ОЗУ.

Я рекомендую вам:
+ поместить код обновления вашего виджета в отдельный класс обслуживания
+ активировать этот класс при возникновении различных событий. onUpdate() и другие события, например, то, которое приводит к очистке вашей оперативной памяти.
+ убедитесь, что вы каждый раз обновляете все с помощью удаленных представлений, потому что старые ожидающие намерения и т. д. не сохраняются.

Вы можете полностью контролировать события, запускающие обновление виджета.

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

На SO много вопросов о том, кому пользоваться сервисом с виджетами. Работа над ним не должна занять много времени. Размещение этой информации здесь выходит за рамки этого вопроса.

person Community    schedule 26.04.2014
comment
Это правда, он полагается только на onUpdate(). Я слышал об использовании службы для этого несколько раз, но я до сих пор не знаю, как использовать ее надлежащим образом. Не могли бы вы привести небольшой пример? Мне просто нужно знать, где запустить эту службу и как она должна выглядеть. Я не знаю, какие события вызывают очистку оперативной памяти ... Android просто делает это, если не хватает свободного места (например, при открытии большого приложения). Я был бы очень рад короткому примеру или дополнительной информации. Спасибо! - person Klumbe; 04.05.2014
comment
Спасибо за объяснение, но я все равно ничего не понимаю. Как передать в службу такую ​​информацию, как AppWidgetManager или appWidgetIds? И даже если я это сделаю, как я могу сработать в нужное время? Я имею в виду, что правильное время должно быть, когда виджет виден. Я спрашиваю себя, как Google сделал это в своем виджете звукового поиска. Теперь есть время между очисткой оперативной памяти и обновлением виджета. Я имею в виду, когда я закрываю приложение, которое вызывает очистку оперативной памяти, это приложение все еще работает, а мое - нет. - person Klumbe; 07.05.2014
comment
Service-Thing не является большой проблемой (у меня он работает), но я до сих пор не знаю, как его вызвать после очистки оперативной памяти (или даже, как вы сказали: после того, как устройство проснется). Я пытался найти ответ (конечно, много часов), но я все еще не продвигаюсь. - person Klumbe; 10.05.2014
comment
Я попробую это: stackoverflow.com/questions/13443543/ Вы имеете в виду это? - person Klumbe; 10.05.2014
comment
Я проведу еще несколько тестов, но я думаю, что это работает как шарм :-) - person Klumbe; 10.05.2014
comment
Я не имел в виду какой-то конкретный ответ, но похоже, что вы это решаете. если вы установите будильник с помощью alarmmanager, то он будет отложен на сон или выключение экрана, а затем сработает, когда телефон по какой-либо причине проснется. Есть довольно много информации о том, как использовать alarmmanager. - person ; 11.05.2014
comment
Да, но дело в том, что (как я знаю) он будет обновлять его на регулярной основе (что не нужно). Но мне просто нужно обновить его, когда фокус теряется или если данные меняются. Меня смущает, что эта служба работает, даже если я не запускаю ее явно. Я просто добавил его в манифест. - person Klumbe; 14.05.2014
comment
Чтобы найти лучший способ обновить мое приложение, мне просто нужно было узнать больше о том, что делает Android и какое событие я хотел использовать для запуска моих обновлений. Я не мог выбрать тот, который мне действительно нужен, потому что Android просто не мог, и мне пришлось пойти на компромисс. Как нуб, мне просто нужно было продолжать учиться и искать, пока я не нашел подходящий способ. Это заняло время, но это был единственный способ заставить мое приложение работать. Stackoverflow полезен для небольших технических вещей, но не для стратегии программирования. - person ; 15.05.2014