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

Как создать постоянный AlarmManager

Изменить: Уточненный вопрос основан на ответе CommonsWare

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

Это проблема для нас, потому что у нас есть приложение-виджет, который отображает время. Это означает, что нам нужно обновлять время каждую минуту. Чтобы обойти 30-минутное ограничение на обновление метода onUpdate для AppWidgetProvider, мы используем AlarmManager. Обычно это работает очень хорошо, но некоторые пользователи сообщают о времени выхода из синхронизации. Поговорив с несколькими из них, мое подозрение в том, что наше приложение убивается вручную с помощью приложения-убийцы задач или Android сам убивает наше приложение.

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

Вот код, который мы выполняем, чтобы запланировать наш будильник:

Intent intent = new Intent(UPDATE_TIME);
PendingIntent pIntent = PendingIntent.getBroadcast(ctx,
  0 /* no requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT );

// get alarm params
Date d = new Date();
long timeTilMinuteChange = 60*1000-d.getSeconds()*1000;
long startTime = System.currentTimeMillis() + + timeTilMinuteChange;

AlarmManager am = (AlarmManager) ctx.getSystemService(Context.
am.cancel(pIntent);
am.set(AlarmManager.RTC, System.currentTimeMillis(), pIntent);
        am.setRepeating(AlarmManager.RTC, startTime, 60000, pIntent);
4b9b3361

Ответ 1

Всякий раз, когда наше приложение убито, AlarmManager также убивается.

AlarmManager не убивается. Однако ваша тревога отменяется. Если пользователь останавливает или останавливает выполнение задачи, ваши аварийные сигналы незапланированы. На Android 3.1+, если пользователь принудительно останавливает вас, ничто из вашего кода не будет запускаться снова до тех пор, пока пользователь не запустит одно из ваших действий.

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

В идеале, ваше приложение не должно быть написано таким образом, что у Android будет какая-то причина, чтобы избавиться от вас. Для того, что вы описываете, вы должны либо использовать getBroadcast() PendingIntent, указывающий на зарегистрированный манифест BroadcastReceiver, либо использовать getService() PendingIntent, указывающий на IntentService. В любом случае ваш код будет выполняться ненадолго, и тогда ваш процесс будет иметь право на восстановление в Android без проблем, если возникнет такая необходимость.

Убийцы задач, будь то ручные или автоматические, кажутся гораздо более вероятными виновниками аварийных сигналов, отмененных, ИМХО.

Ответ 2

О диспетчере аварий в Docs - объяснение несколько сбивает с толку, и я честно все еще не понимаю его полностью. У меня есть этот бит кода для части виджета, который решил проблему в моем случае.

package com.test.mytestwidget;

import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;  

public class MyWidgetProvider extends AppWidgetProvider {   

    private PendingIntent service = null;  

    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);                

        final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);  

        final Calendar TIME = Calendar.getInstance();  
        TIME.set(Calendar.MINUTE, 0);  
        TIME.set(Calendar.SECOND, 0);  
        TIME.set(Calendar.MILLISECOND, 0);  

        final Intent i = new Intent(context, UpdateWidgetService.class);  

        if (service == null)  
        {  
            service = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);  
        }  

        m.setRepeating(AlarmManager.RTC, TIME.getTime().getTime(), 30000, service);  

     }

     @Override  
     public void onDisabled(Context context)  
     {              
         final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);  

         m.cancel(service);  
         super.onDisabled(context);
     }      

}