Как создать постоянный 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);
2 ответа
Всякий раз, когда наше приложение убивается, AlarmManager также убивается.
AlarmManager
не убит. Ваша тревога, однако, отменена. Если пользователь принудительно останавливает вас или убивает задачу, ваши тревоги не планируются. В Android 3.1+, если пользователь принудительно останавливает вас, ваш код не будет выполняться снова, пока пользователь не запустит одно из ваших действий вручную.
После разговора с несколькими из них я подозреваю, что наше приложение убивается вручную через приложение-убийцу задач, или Android сам убивает наше приложение.
В идеале, ваше приложение не должно быть написано так, чтобы у Android была причина избавиться от вас. Для чего-то вроде того, что вы описываете, вы должны либо использовать getBroadcast()
PendingIntent
указывая на манифест зарегистрирован BroadcastReceiver
или вы должны использовать getService()
PendingIntent
указывая на IntentService
, В любом случае ваш код будет работать недолго, и тогда ваш процесс будет иметь право на восстановление Android без проблем, если возникнет такая необходимость.
Убийцы задач, будь то ручные или автоматические, кажутся гораздо более вероятным виновником отмены аварий, ИМХО.
Насчет менеджера по тревоге в Документах - объяснение несколько запутанное, и я, честно говоря, до сих пор не понимаю его полностью. У меня есть этот кусок кода для части виджета, который решил проблему в моем случае.
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);
}
}