Come verificare se AlarmManager ha già impostato un allarme?


182

All'avvio dell'app, desidero controllare se un particolare allarme (registrato tramite AlarmManager) è già impostato e in esecuzione. I risultati di Google sembrano indicare che non c'è modo di farlo. È ancora corretto? Ho bisogno di fare questo controllo per avvisare l'utente prima che venga intrapresa un'azione per creare un nuovo allarme.

  0

Si prega di convalidare la risposta che ha risolto il problema o per posta la vostra soluzione. 16 gen. 172017-01-16 22:13:53

-3

Stai parlando della sveglia - quale fonte si può scaricare da qui - https://android.googlesource.com/platform/packages/apps/AlarmClock

o si sta parlando di impostare il tempo in cui deve essere eseguito determinato compito - http://developer.android.com/reference/android/app/AlarmManager.html

  0

lo hanno rinominato in DeskClock: http://android.git.kernel.org/?p=platform/packages/apps/DeskClock.git;a=summary 29 dic. 102010-12-29 18:41:20

  0

Mi riferisco a un allarme impostato nel mio codice utilizzando AlarmManager. Non riesco a trovare alcun metodo per verificare se un allarme è già impostato per un particolare intento. Poiché il programma consente all'utente di impostare un allarme e quindi chiudere l'app, desidero sapere quando l'app è aperta, se è impostato un allarme e se è in esecuzione "fuori dalla vista". 29 dic. 102010-12-29 19:41:19

  0

Sembra che la classe AlarmManager non fornisca tale funzionalità. Qui puoi dare un'occhiata alla fonte di AlarmManager - http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/app/AlarmManager.java Se sei davvero disperato, puoi estenderlo (o reimplementare IAlarmManager) e creare il tuo gestore di allarmi. Eccessivo. Aggiornamento 29 dic. 102010-12-29 20:18:28

  0

: Ho scoperto da un altro thread che il seguente sembra svolgere il lavoro: - 30 dic. 102010-12-30 13:27:22

+6

allarmi = (AlarmManager) getSystemService (Context.ALARM_SERVICE); \t Stringa ALARM_ACTION; ALARM_ACTION = AAAlarmReceiver.ACTION_LOAD_LISTVIEW; Intento intentToFire = new Intent (ALARM_ACTION); boolean alarmUp = (PendingIntent.getBroadcast (cText, 0, intentToFire, PendingIntent.FLAG_NO_CREATE)! = Null); 30 dic. 102010-12-30 13:27:40

  0

Si prega di rispondere solo a quello specifico nella risposta. Se vuoi fare una domanda o qualsiasi altra cosa, tienilo nel commento. 01 dic. 172017-12-01 10:39:08

  0

@RahatZaman Di cosa stai parlando? Una delle principali filosofie di overflow dello stack è "Dai a un uomo un pesce e dagli da mangiare per un giorno. Insegna a un uomo a pescare e lo nutri per tutta la vita '. Quindi, indicare la fonte della lib è una pratica abbastanza comune qui. 05 dic. 172017-12-05 10:06:25


1

Im sotto l'impressione che theres nessun modo per farlo, sarebbe carino però.

È possibile ottenere un risultato simile avendo Alarm_last_set_time registrato da qualche parte e avendo un OnRroot_Start BroadcastReceever: BOOT_COMPLETED qualcosa di simile.


277

Seguito sul commento pubblicato, ecco la soluzione dettagliata. Diciamo che è stato registrato un allarme ripetuto con un intento attesa come questo:

Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION"); 
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, 
             intent, PendingIntent.FLAG_UPDATE_CURRENT); 
Calendar calendar = Calendar.getInstance(); 
calendar.setTimeInMillis(System.currentTimeMillis()); 
calendar.add(Calendar.MINUTE, 1); 

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 1000 * 60, pendingIntent); 

Il modo in cui si controlla per vedere se è attivo è quello di:

boolean alarmUp = (PendingIntent.getBroadcast(context, 0, 
     new Intent("com.my.package.MY_UNIQUE_ACTION"), 
     PendingIntent.FLAG_NO_CREATE) != null); 

if (alarmUp) 
{ 
    Log.d("myTag", "Alarm is already active"); 
} 

La chiave qui è la FLAG_NO_CREATE che come descritto in javadoc: if the described PendingIntent **does not** already exists, then simply return null (invece di crearne uno nuovo)

+8

Deve usare l'intento con solo una stringa di azione? Ho provato a specificare una classe, nuovo Intent (context, MyClass.class) ma non sembra funzionare. Restituisce sempre nulla anche quando l'allarme è in esecuzione. 04 apr. 122012-04-04 08:39:49

+5

toc777, non è necessario che sia una stringa che corrisponde a un'azione dichiarata nel filtro intentato nel manifest.xml 11 apr. 122012-04-11 08:27:24

+4

Chris, era un altro problema che stava causando il mio problema. L'intento che ho menzionato sopra in realtà funziona :) 12 apr. 122012-04-12 12:25:50

  0

Un problema che avevo non era chiamare annullare su ENTRAMBI alarmManager e su PendingIntent. I.E ~ alarmMgr.cancel (alarmIntent); alarmIntent.cancel(); 29 mag. 142014-05-29 12:01:21

  0

@ChrisKnight: Funzionerà ancora se controllo da un'app dire app1 se è impostato un allarme e funziona in app2? e inoltre, gli allarmi si esauriscono durante l'aggiornamento di un'app e quindi è necessario ripristinarlo di nuovo (per il caso di aggiornamento dell'app)? 08 lug. 142014-07-08 03:25:46

+1

Restituisce sempre TRUE dicendo che l'intento in sospeso esiste già. Anche dopo la disinstallazione e la reinstallazione dell'app. Quanto dura l'intento in sospeso? 13 ago. 142014-08-13 20:33:24

+30

Si noti che è necessario chiamare sia '' 'alarmManager.cancel (pendingIntent)' '' che '' 'pendingIntent.cancel()' '' affinché questa soluzione restituisca false. 29 set. 142014-09-29 20:00:44

+1

per gli utenti che utilizzano il nuovo intent (context, YourService.class), è possibile utilizzare .setAction ("ACTIONNAME") per definire un'azione sull'iniziativa. 28 nov. 142014-11-28 20:11:13

+1

Lifesaver. Tieni presente che dovrai creare l'intento esattamente nello stesso modo in cui lo hai creato prima, ad eccezione delle bandiere. 26 feb. 152015-02-26 10:07:31

+22

In questo caso non è ovvio, il codice in questa risposta non verifica che l'intento in sospeso sia stato registrato con il gestore degli allarmi. Il codice verifica semplicemente che PendingIntent sia stato creato tramite getBroadcast con un obiettivo di destinazione equivalente. Puoi provarlo eseguendo il codice alarmUp dopo il getBroadcast, ma prima di tutto il calendario e il gestore degli allarmi. Restituirà vero. Questo fatto spiega perché devi PendingIntent.cancel per ottenere il valore per tornare a false. In senso stretto, questo non risponde alla domanda. 21 apr. 152015-04-21 21:09:49

+1

Scusami. Voglio chiedere cosa è MY_UNIQUE_ACTION? Da dove viene? 23 lug. 152015-07-23 01:14:26

+1

@LeonardFebrianto penso che sia stata una risposta attesa da tempo ma sono abbastanza sicuro che tu abbia avuto la ragione. Questo è solo il nome dell'azione, può essere qualsiasi costante di azione che hai associato con i ricevitori nel tuo manifest 15 dic. 152015-12-15 05:49:51

  0

non funziona se l'allarme viene ucciso da "force stop" ecc. Deve essere cancellato prima di usare questo codice 17 dic. 152015-12-17 13:55:17

+1

Ho provato Intento intento = nuovo Intento (ctx, MyReceiver.class); invece di passare unique_action e ha funzionato :) 22 dic. 152015-12-22 11:24:16

  0

ohh funziona grazie! 23 dic. 152015-12-23 03:46:33

+1

consiglio per i futuri lettori - Assicurati di non sbagliare PendingIntent.getBroadcast (...) con PendingIntent.getService (...) - risparmia qualche problema! :) 18 apr. 162016-04-18 04:33:00

+2

questa è la prima volta che vedo una risposta WRONG così alta. Vedi il commento di bigh_29. 03 gen. 172017-01-03 20:29:37


7

Ho 2 allarmi. Sto usando intenti con extra invece di intervenire per identificare gli eventi:

Intent i = new Intent(context, AppReciever.class); 
i.putExtra("timer", "timer1"); 

il fatto è che con extra diff l'intento (e l'allarme) wont essere unico nel suo genere. Quindi, per poter identificare quale allarme è attivo o no, dovessi definire diff requestCode -s:

boolean alarmUp = (PendingIntent.getBroadcast(context, MyApp.TIMER_1, i, 
        PendingIntent.FLAG_NO_CREATE) != null); 

ed ecco come è stato creato allarme:

public static final int TIMER_1 = 1; 
public static final int TIMER_2 = 2; 

PendingIntent pending = PendingIntent.getBroadcast(context, TIMER_1, i, 
      PendingIntent.FLAG_CANCEL_CURRENT); 
setInexactRepeating(AlarmManager.RTC_WAKEUP, 
      cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pending); 
pending = PendingIntent.getBroadcast(context, TIMER_2, i, 
      PendingIntent.FLAG_CANCEL_CURRENT); 
setInexactRepeating(AlarmManager.RTC_WAKEUP, 
      cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pending); 
  0

Utilizzo degli extra di intent e questa soluzione ha funzionato per me. Solo una modifica è che sto usando il servizio quindi l'ho cambiato in 'PendingIntent.getService' 27 ago. 162016-08-27 10:07:25


92

Per gli altri che possono avere bisogno di questo, ecco una risposta

Usa adb shell dumpsys alarm

È possibile conoscere l'allarme è stato impostato e quando stanno andando a allarmata e l'intervallo. Inoltre, quante volte questo allarme è stato invocato.

+4

questa dovrebbe essere la risposta giusta 04 ott. 142014-10-04 22:07:13

+1

Questo è esattamente 09 dic. 142014-12-09 12:43:14

+24

Non proprio una risposta programmatica all'OP, ma un consiglio interessante. Molto buono a sapersi. 06 mag. 152015-05-06 17:38:12

+1

aggiungere un grep per filtrare l'elenco di allarmi di solito lungo: 'adb shell dumpsys alarm | grep <e.g. nome del pacchetto della tua app> 'Funziona anche su nuovi sistemi Windows (io uso Win10) 08 ago. 162016-08-08 10:51:30

+2

grep viene eseguito sul dispositivo mobile, non sul PC. Quindi se grep funziona dipende dal sistema operativo Android. I vecchi telefoni non vengono con grep. 07 mar. 172017-03-07 13:15:26


36

Esempio di funzionamento con ricevitore (la risposta più alta era solo con azione).

//starting 
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); 
Intent intent = new Intent(getActivity(), MyReceiver.class); 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//my custom string action name 
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//used unique ID as 1001 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), aroundInterval, pendingIntent);//first start will start asap 

//and stopping 
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up 
PendingIntent pendingIntent = PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_CANCEL_CURRENT);//the same as up 
alarmManager.cancel(pendingIntent);//important 
pendingIntent.cancel();//important 

//checking if alram is working with pendingIntent 
Intent intent = new Intent(getActivity(), MyReceiver.class);//the same as up 
intent.setAction(MyReceiver.ACTION_ALARM_RECEIVER);//the same as up 
boolean isWorking = (PendingIntent.getBroadcast(getActivity(), 1001, intent, PendingIntent.FLAG_NO_CREATE) != null);//just changed the flag 
Log.d(TAG, "alarm is " + (isWorking ? "" : "not") + " working..."); 

ho descritto anche sul mio blog

+1

Non sono sicuro che sia sufficiente. Nel caso in cui un PendingIntent sia registrato con AlarmManager e quindi interrotto da entrambi i metodi di annullamento, 'isWorking' sopra sarà ancora true. Sembra che PendingIntent non sia stato rimosso da AlarmManager e continuerà a restituire un'istanza. Come possiamo quindi sapere efficacemente quando gli allarmi sono stati attivati ​​/ disattivati? 10 giu. 162016-06-10 07:36:29

  0

Questo ha funzionato perfettamente. Cose da notare: setAction() e requestCode() devono essere identici in tutti i getBroadcast() e vale la pena disinstallare l'app dal dispositivo. Questo mi ha sorpreso. Grazie 11 giu. 162016-06-11 10:12:42

  0

Funziona alla grande. Grazie! 01 set. 162016-09-01 12:59:48

  0

Bel esempio ma non vorrei usare 1001 come codice di richiesta privata lì. Solo 0 per rendere l'esempio più ovvio. 09 lug. 172017-07-09 08:12:57


29

Nota questa citazione dalla documentazione per il gestore di allarme:

Se c'è già un allarme per questo intento in programma (con la l'uguaglianza di due intenti essendo definita da Intent.filterEquals), quindi lo verrà rimosso e sostituito da questo.

Non preoccuparsi di chiedere se l'allarme esiste se si sta tentando di decidere se creare un allarme o meno. Basta crearlo ogni volta che la tua app si avvia. Sostituirai tutti gli allarmi passati che hai configurato.

È necessario un approccio diverso se si sta tentando di calcolare quanto tempo rimane su un allarme creato in precedenza o se è davvero necessario sapere se tale allarme esiste anche. Per rispondere a queste domande, prendi in considerazione la possibilità di salvare i pref pref condivisi al momento della creazione dell'allarme. È possibile memorizzare il timestamp dell'orologio nel momento in cui è stato impostato l'allarme, il momento in cui si prevede che l'allarme si attivi e il periodo di ripetizione (se si imposta un allarme ripetuto).

  0

Secondo me questa dovrebbe essere la risposta accettata. A meno che l'OP non abbia una situazione speciale che giustifica la mancata ripetizione dell'allarme 19 mag. 162016-05-19 16:11:12

  0

Nel mio caso, voglio sapere se l'allarme è già impostato e in tal caso non voglio crearne uno nuovo o resettare l'allarme esistente. 21 lug. 172017-07-21 14:00:12


3

Ho creato uno script bash semplice (stupido o non), che estrae i long dalla shell adb, li converte in timestamp e lo mostra in rosso.

echo "Please set a search filter" 
read search 

adb shell dumpsys alarm | grep $search | (while read i; do echo $i; _DT=$(echo $i | grep -Eo 'when\s+([0-9]{10})' | tr -d '[[:alpha:][:space:]]'); if [ $_DT ]; then echo -e "\e[31m$(date -d @$_DT)\e[0m"; fi; done;) 

provarlo;)


2
Intent intent = new Intent("com.my.package.MY_UNIQUE_ACTION"); 
      PendingIntent pendingIntent = PendingIntent.getBroadcast(
        sqlitewraper.context, 0, intent, 
        PendingIntent.FLAG_NO_CREATE); 

FLAG_NO_CREATE non è creare attesa di intenti in modo che dà valore booleano falso.

  boolean alarmUp = (PendingIntent.getBroadcast(sqlitewraper.context, 0, 
        new Intent("com.my.package.MY_UNIQUE_ACTION"), 
        PendingIntent.FLAG_NO_CREATE) != null); 

      if (alarmUp) { 
       System.out.print("k"); 

      } 

      AlarmManager alarmManager = (AlarmManager) sqlitewraper.context 
        .getSystemService(Context.ALARM_SERVICE); 
      alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
        System.currentTimeMillis(), 1000 * 60, pendingIntent); 

Dopo controllare l'AlarmManager il valore di attesa intenti Dà vero perché AlarmManager Aggiornamento La bandiera di intenti in attesa.

  boolean alarmUp1 = (PendingIntent.getBroadcast(sqlitewraper.context, 0, 
        new Intent("com.my.package.MY_UNIQUE_ACTION"), 
        PendingIntent.FLAG_UPDATE_CURRENT) != null); 
      if (alarmUp1) { 
       System.out.print("k"); 

      } 

5

appena trovato un'altra soluzione, che sembra funzionare per me

Intent myIntent = new Intent(MainActivity.this, MyReceiver.class); 

boolean isWorking = (PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_NO_CREATE) != null); 
if (isWorking) {Log.d("alarm", "is working");} else {Log.d("alarm", "is not working");} 

if(!isWorking) { 
    pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT); 
    alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 
    int timeNotif = 5 * 60 * 1000;//time in ms, 7*24*60*60*1000 for 1 week 
    Log.d("Notif", "Notification every (ms): " + timeNotif); 
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), timeNotif, pendingIntent); 
    } 
  0

A volte, su Marshmallow, dopo aver forzato l'interruzione di un'app, getBroadcast() restituirà un valore non nullo, ma l'allarme non viene impostato. 15 feb. 182018-02-15 20:14:10