web-dev-qa-db-fra.com

Comment vérifier si AlarmManager a déjà une alarme configurée?

Lorsque mon application démarre, je souhaite qu'elle vérifie si une alarme particulière (enregistrée via AlarmManager) est déjà définie et en cours d'exécution. Les résultats de Google semblent indiquer qu'il n'y a aucun moyen de le faire. Est-ce toujours correct? J'ai besoin de faire cette vérification afin d'avertir l'utilisateur avant toute action visant à créer une nouvelle alarme.

216
ron

Pour faire suite au commentaire posté, voici la solution détaillée. Supposons que vous ayez enregistré une alarme répétée avec une intention en attente comme celle-ci:

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

Pour vérifier s’il est actif, vous devez:

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 clé ici est le FLAG_NO_CREATE qui, comme décrit dans le javadoc: if the described PendingIntent **does not** already exists, then simply return null (au lieu d'en créer un nouveau)

308
Chris Knight

Pour ceux qui en ont besoin, voici une réponse.

Utilisez adb Shell dumpsys alarm

Vous pouvez savoir que l'alarme a été réglée et quand vont-ils sonner l'alarme et l'intervalle. Aussi combien de fois cette alarme a été invoquée.

109
Jack Feng

Exemple de travail avec le récepteur (la réponse principale était simplement avec l'action).

//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 alarm 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...");

Il convient de mentionner:

Si l'application de création crée ultérieurement (processus) le même type de PendingIntent (idem opération, idem Intent - action, données, catégories, composants, indicateurs), il reçoit un PendingIntent représentant le même jeton s'il est toujours valide, et peut donc appeler cancel () pour le supprimer.

En bref, votre PendingIntent devrait avoir les mêmes fonctionnalités (structure d'opération et d'intention) pour en prendre le contrôle.

48
deadfish

Remarque cette citation à partir de la documentation pour la méthode de configuration de Alarm Manager:

S'il existe déjà une alarme pour cette intention planifiée (l'égalité des deux intentions étant définie par Intent.filterEquals), elle sera alors supprimée et remplacée par celle-ci.

Si vous savez que vous voulez que l'alarme soit réglée, vous n'avez pas besoin de vérifier si elle existe déjà ou non. Il suffit de le créer à chaque démarrage de votre application. Vous allez remplacer toutes les alarmes passées par les mêmes Intent.

Vous avez besoin d'une approche différente si vous essayez de calculer le temps qu'il reste à une alarme créée précédemment ou si vous avez réellement besoin de savoir si une telle alarme existe. Pour répondre à ces questions, envisagez de sauvegarder les données préf partagées au moment de la création de l'alarme. Vous pouvez enregistrer l'horodatage de l'horloge au moment où l'alarme est réglée, l'heure à laquelle vous prévoyez de l'alarme et la période de répétition (si vous configurez une alarme à répétition).

41
bigh_29

J'ai 2 alarmes. J'utilise l'intention avec des extras au lieu d'action pour identifier les événements:

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

le fait est qu'avec des suppléments, l'intention (et l'alarme) ne sera pas unique. Donc, pour pouvoir identifier quelle alarme est active ou non, je devais définir diff requestCode- s:

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

et voici comment alarm a été créé:

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);
10
HiB

Je viens de trouver une autre solution, cela semble fonctionner pour moi

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

Alors que presque tout le monde a donné la bonne réponse, personne n’a expliqué sur quelle base le système Alarms fonctionne.

Vous pouvez en apprendre plus sur AlarmManager et son fonctionnement ici . Mais voici la réponse rapide

Vous voyez AlarmManager planifie essentiellement un PendingIntent à un moment donné dans l’avenir. Donc, pour annuler l’alarme programmée, vous devez annuler le PendingIntent.

Notez toujours deux choses lorsque vous créez la PendingIntent

PendingIntent.getBroadcast(context,REQUEST_CODE,intent, PendingIntent.FLAG_UPDATE_CURRENT);
  • Code de demande - sert d'identifiant unique
  • Flag - Définit le comportement de PendingIntent

Maintenant, pour vérifier si l’alarme est déjà programmée ou pour annuler l’alarme, il vous suffit d’avoir accès au même PendingIntent. Cela peut être fait si vous utilisez le même code de requête et utilisez FLAG_NO_CREATE comme indiqué ci-dessous

PendingIntent pendingIntent=PendingIntent.getBroadcast(this,REQUEST_CODE,intent,PendingIntent.FLAG_NO_CREATE);

if (pendingIntent!=null)
   alarmManager.cancel(pendingIntent);

Avec FLAG_NO_CREATE, il retournera null si le PendingIntent n'existe pas déjà. S'il existe déjà, il renvoie une référence à l'existant PendingIntent

3
IrshadKumail

J'ai créé un script bash simple (stupide ou non), qui extrait les fichiers longs du shell adb, les convertit en horodatages et les affiche en rouge.

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

essayez-le;)

3
Jan Ni
    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 n'est pas une intention en attente de création, il donne donc la valeur booléenne false.

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

Une fois que AlarmManager a vérifié la valeur de l'intention en attente, la valeur est true car AlarmManager a mis à jour l'indicateur d'intention en attente.

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

            }
1
MIkka Marmik

J'ai l'impression qu'il n'y a aucun moyen de le faire, ce serait bien.

Vous pouvez obtenir un résultat similaire en ayant un Alarm_last_set_time enregistré quelque part et en ayant un peu On_boot_starter BroadcastReciever: BOOT_COMPLETED.

0
Stephen