Programmer des alarmes

Les alarmes (basées sur la classe AlarmManager) vous permettent d'effectuer des opérations temporelles en dehors de la durée de vie de votre application. Par exemple, vous pouvez utiliser une alarme pour lancer une opération de longue durée, comme démarrer un service une fois par jour pour télécharger les prévisions météo.

Les alarmes présentent les caractéristiques suivantes :

  • Ils vous permettent de déclencher des intents à des heures et/ou intervalles définis.

  • Vous pouvez les utiliser conjointement avec des récepteurs de diffusion pour planifier des jobs ou des WorkRequests afin d'effectuer d'autres opérations.

  • Ils fonctionnent en dehors de votre application. Vous pouvez donc les utiliser pour déclencher des événements ou des actions même lorsque votre application n'est pas en cours d'exécution et même si l'appareil lui-même est en veille.

  • Ils vous aident à minimiser les besoins en ressources de votre application. Vous pouvez planifier des opérations sans avoir à vous appuyer sur des minuteurs ni sur des services fonctionnant en continu.

Définir une alarme inexacte

Lorsqu'une application définit une alarme inexacte, le système la déclenche à un moment donné dans le futur. Les alarmes inexactes offrent certaines garanties concernant le moment de la diffusion de l'alarme tout en respectant les restrictions d'économie de batterie telles que Doze.

Les développeurs peuvent tirer parti des garanties d'API suivantes pour personnaliser le calendrier de diffusion des alarmes inexactes.

Déclencher une alarme après un certain temps

Si votre application appelle set(), setInexactRepeating() ou setAndAllowWhileIdle(), l'alarme ne se déclenche jamais avant l'heure de déclenchement fournie.

Sur Android 12 (niveau d'API 31) ou version ultérieure, le système déclenche l'alarme dans l'heure qui suit l'heure de déclenchement fournie, sauf si des restrictions d'économie de batterie sont en vigueur, telles que l'économiseur de batterie ou Doze.

Déclencher une alarme pendant une période donnée

Si votre application appelle setWindow(), l'alarme ne se déclenche jamais avant l'heure de déclenchement fournie. Sauf si des restrictions d'économie de batterie sont en vigueur, l'alarme est déclenchée dans le délai spécifié, à partir de l'heure de déclenchement indiquée.

Si votre application cible Android 12 ou une version ultérieure, le système peut retarder l'invocation d'une alarme inexacte avec une fenêtre temporelle d'au moins 10 minutes. Pour cette raison, les valeurs du paramètre windowLengthMillis sous 600000 sont tronquées à 600000.

Déclencher une alarme récurrente à intervalles plus ou moins réguliers

Si votre application appelle setInexactRepeating(), le système déclenche plusieurs alarmes :

  1. La première alarme se déclenche dans le délai spécifié, à partir de l'heure de déclenchement indiquée.
  2. Les alarmes suivantes se déclenchent généralement une fois le délai spécifié écoulé. Le délai entre deux invocations consécutives de l'alarme peut varier.

Régler une alarme exacte

Le système déclenche une alarme exacte à un moment précis dans le futur.

La plupart des applications peuvent planifier des tâches et des événements à l'aide d'alarmes inexactes pour effectuer plusieurs cas d'utilisation courants. Si la fonctionnalité principale de votre application dépend d'une alarme à heure précise (par exemple, une application d'horloge ou d'agenda), vous pouvez utiliser une alarme exacte.

Cas d'utilisation ne nécessitant pas forcément d'alarme exacte

La liste suivante répertorie les workflows courants ne nécessitant pas obligatoirement une alarme exacte :

Planifier des opérations de minutage pendant la durée de vie de votre application
La classe Handler inclut plusieurs méthodes efficaces pour gérer les opérations de minutage, comme effectuer une tâche toutes les n secondes pendant que votre application est active : postAtTime() et postDelayed(). Notez que ces API s'appuient sur la disponibilité du système et non sur le temps réel.
Travail d'arrière-plan planifié, comme la mise à jour de votre application et l'importation de journaux
WorkManager permet de planifier des tâches périodiques sensibles au facteur temps. Vous pouvez fournir un intervalle de répétition et un flexInterval (15 minutes minimum) pour définir un environnement d'exécution précis pour le travail.
Action spécifiée par l'utilisateur devant se produire après une heure précise (même si le système est en veille)
Utilisez une alarme inexacte. Plus précisément, appelez setAndAllowWhileIdle().
Action spécifiée par l'utilisateur devant se produire après une heure précise
Utilisez une alarme inexacte. Plus précisément, appelez set().
Action spécifiée par l'utilisateur pouvant se produire dans un délai donné
Utilisez une alarme inexacte. Plus précisément, appelez setWindow(). Notez que si votre application cible Android 12 ou version ultérieure, la durée de fenêtre la plus courte autorisée est de 10 minutes.

Régler une alarme exacte

Votre application peut définir des alarmes exactes à l'aide de l'une des méthodes suivantes. Ces méthodes sont classées de sorte que celles qui se trouvent en bas de la liste servent des tâches plus urgentes, mais nécessitent plus de ressources système.

setExact()

Appeler une alarme à une heure future presque précise, à condition que d'autres mesures d'économie de batterie ne soient pas en vigueur.

Utilisez cette méthode pour définir des alarmes exactes, sauf si le travail de votre application est urgent pour l'utilisateur.

setExactAndAllowWhileIdle()

Déclenchez une alarme à une heure future presque précise, même si des mesures d'économie de batterie sont en vigueur.

setAlarmClock()

Déclencher une alarme à une heure précise dans le futur. Étant donné que ces alarmes sont très visibles pour les utilisateurs, le système n'ajuste jamais leur heure de diffusion. Le système identifie ces alarmes comme les plus critiques et quitte les modes basse consommation si nécessaire pour les diffuser.

Consommation des ressources système

Lorsque le système déclenche des alarmes exactes définies par votre application, l'appareil consomme beaucoup de ressources, comme l'autonomie de la batterie, en particulier s'il est en mode Économie d'énergie. De plus, le système ne peut pas facilement regrouper ces requêtes pour utiliser les ressources plus efficacement.

Nous vous recommandons vivement de créer une alarme inexacte chaque fois que possible. Pour effectuer des tâches plus longues, planifiez-les à l'aide de WorkManager ou JobScheduler à partir de l'BroadcastReceiver de votre alarme. Pour effectuer des tâches lorsque l'appareil est en mode veille, créez une alarme inexacte à l'aide de setAndAllowWhileIdle() et démarrez une tâche à partir de l'alarme.

Déclarer l'autorisation d'alarme exacte appropriée

Si votre application cible Android 12 ou version ultérieure, vous devez obtenir l'accès spécifique aux applications "Alarmes et rappels". Pour ce faire, déclarez l'autorisation SCHEDULE_EXACT_ALARM dans le fichier manifeste de votre application, comme indiqué dans l'extrait de code suivant :

<manifest ...>
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

Si votre application cible Android 13 (niveau d'API 33) ou version ultérieure, vous pouvez déclarer l'autorisation SCHEDULE_EXACT_ALARM ou USE_EXACT_ALARM.

<manifest ...>
    <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
    <application ...>
        ...
    </application>
</manifest>

Bien que les autorisations SCHEDULE_EXACT_ALARM et USE_EXACT_ALARM signalent les mêmes fonctionnalités, elles sont accordées différemment et prennent en charge différents cas d'utilisation. Votre application ne doit utiliser des alarmes exactes et déclarer l'autorisation SCHEDULE_EXACT_ALARM ou USE_EXACT_ALARM que si une fonction visible par l'utilisateur dans votre application nécessite des actions à un moment précis.

USE_EXACT_ALARM

SCHEDULE_EXACT_ALARM

  • Accordé par l'utilisateur
  • Ensemble plus large de cas d'utilisation
  • Les applications doivent confirmer que l'autorisation n'a pas été révoquée.

L'autorisation SCHEDULE_EXACT_ALARM n'est pas accordée par défaut aux nouvelles installations d'applications ciblant Android 13 (niveau d'API 33) ou version ultérieure. Si un utilisateur transfère des données d'application vers un appareil exécutant Android 14 via une opération de sauvegarde et de restauration, l'autorisation SCHEDULE_EXACT_ALARM sera refusée sur le nouvel appareil. Toutefois, si une application existante dispose déjà de cette autorisation, elle sera pré-accordée lorsque l'appareil passera à Android 14.

Remarque : Si l'alarme exacte est définie à l'aide d'un objet OnAlarmListener, comme avec l'API setExact, l'autorisation SCHEDULE_EXACT_ALARM n'est pas requise.

Utiliser l'autorisation SCHEDULE_EXACT_ALARM

Contrairement à USE_EXACT_ALARM, l'autorisation SCHEDULE_EXACT_ALARM doit être accordée par l'utilisateur. L'utilisateur et le système peuvent révoquer l'autorisation SCHEDULE_EXACT_ALARM.

Pour vérifier si l'autorisation est accordée à votre application, appelez canScheduleExactAlarms() avant d'essayer de définir une alarme exacte. Lorsque l'autorisation SCHEDULE_EXACT_ALARM est révoquée pour votre application, celle-ci s'arrête et toutes les futures alarmes exactes sont annulées. Cela signifie également que la valeur renvoyée par canScheduleExactAlarms() reste valide pendant tout le cycle de vie de votre application.

Lorsque l'autorisation SCHEDULE_EXACT_ALARMS est accordée à votre application, le système lui envoie la diffusion ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED. Votre application doit implémenter un récepteur de diffusion qui effectue les opérations suivantes :

  1. Confirme que votre application dispose toujours de l'accès spécial aux applications. Pour ce faire, appelez canScheduleExactAlarms(). Cette vérification protège votre application dans le cas où l'utilisateur accorde l'autorisation à votre application, puis la révoque presque immédiatement après.
  2. Reprogramme les alarmes exactes dont votre application a besoin, en fonction de son état actuel. Cette logique doit être semblable à celle de votre application lorsqu'elle reçoit la diffusion ACTION_BOOT_COMPLETED.

Demander aux utilisateurs d'accorder l'autorisation SCHEDULE_EXACT_ALARM

L&#39;option s&#39;intitule &quot;Autoriser à définir des alarmes et des rappels&quot;.
Figure 1. Page "Alarmes et rappels" dans les paramètres système, où les utilisateurs peuvent autoriser votre application à définir des alarmes exactes.

Si nécessaire, vous pouvez rediriger les utilisateurs vers l'écran Alarmes et rappels dans les paramètres système, comme illustré dans la figure 1. Pour ce faire, procédez comme suit :

  1. Dans l'UI de votre application, expliquez à l'utilisateur pourquoi votre application doit programmer des alarmes exactes.
  2. Appelez un intent qui inclut l'action ACTION_REQUEST_SCHEDULE_EXACT_ALARM.

Définir une alarme récurrente

Les alarmes récurrentes permettent au système d'envoyer des notifications à votre application de manière récurrente.

Une alarme mal conçue peut décharger la batterie et exercer une charge importante sur les serveurs. Pour cette raison, sur Android 4.4 (niveau d'API 19) et versions ultérieures, toutes les alarmes récurrentes sont des alarmes inexactes.

Une alarme récurrente présente les caractéristiques suivantes :

  • Type d'alarme. Pour en savoir plus, consultez Choisir un type d'alarme.

  • Heure de déclenchement. Si l'heure de déclenchement que vous spécifiez est passée, l'alarme se déclenche immédiatement.

  • Intervalle de l'alarme. Par exemple, une fois par jour, toutes les heures ou toutes les cinq minutes.

  • Intent en attente qui se déclenche lorsque l'alarme se déclenche. Lorsque vous définissez une deuxième alarme qui utilise la même intention en attente, elle remplace l'alarme d'origine.

Pour annuler un PendingIntent(), transmettez FLAG_NO_CREATE à PendingIntent.getService() pour obtenir une instance de l'intention (si elle existe), puis transmettez cette intention à AlarmManager.cancel().

Kotlin

val alarmManager =
    context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
val pendingIntent =
    PendingIntent.getService(context, requestId, intent,
                                PendingIntent.FLAG_NO_CREATE)
if (pendingIntent != null && alarmManager != null) {
  alarmManager.cancel(pendingIntent)
}

Java

AlarmManager alarmManager =
    (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent =
    PendingIntent.getService(context, requestId, intent,
                                PendingIntent.FLAG_NO_CREATE);
if (pendingIntent != null && alarmManager != null) {
  alarmManager.cancel(pendingIntent);
}

Choisir un type d'alarme

L'une des premières choses à prendre en compte lors de l'utilisation d'une alarme récurrente est son type.

Il existe deux types d'horloge pour les alarmes : "temps réel écoulé" et "horloge temps réel" (RTC, real time clock). Le temps réel écoulé utilise le "temps écoulé depuis le démarrage du système" comme référence, et l'horloge en temps réel utilise l'heure UTC (horloge murale). Cela signifie que le temps réel écoulé est adapté à la définition d'une alarme basée sur le temps qui s'écoule (par exemple, une alarme qui se déclenche toutes les 30 secondes), car il n'est pas affecté par le fuseau horaire ni par les paramètres régionaux. Le type d'horloge en temps réel est plus adapté aux alarmes qui dépendent des paramètres régionaux actuels.

Les deux types ont une version "réveil", qui indique de réveiller le processeur de l'appareil si l'écran est éteint. Cela garantit que l'alarme se déclenchera à l'heure prévue. Cela peut être utile si votre application a une dépendance temporelle. Par exemple, si elle dispose d'une fenêtre limitée pour effectuer une opération spécifique. Si vous n'utilisez pas la version "réveil" de votre type d'alarme, toutes les alarmes récurrentes se déclencheront la prochaine fois que votre appareil sera réveillé.

Si vous avez simplement besoin que votre alarme se déclenche à un intervalle particulier (par exemple, toutes les demi-heures), utilisez l'un des types de temps réel écoulé. En général, cette option est la plus appropriée.

Si vous avez besoin que votre alarme se déclenche à une heure précise de la journée, choisissez l'un des types d'horloge en temps réel basés sur l'horloge. Notez toutefois que cette approche peut présenter certains inconvénients. L'application peut ne pas être bien traduite dans d'autres paramètres régionaux. De plus, si l'utilisateur modifie le paramètre d'heure de l'appareil, cela peut entraîner un comportement inattendu dans votre application. Comme indiqué ci-dessus, l'utilisation d'un type d'alarme d'horloge temps réel n'est pas non plus une solution évolutive. Nous vous recommandons d'utiliser une alarme "temps réel écoulé" si possible.

Voici la liste des types :

  • ELAPSED_REALTIME : déclenche l'intent en attente en fonction du temps écoulé depuis le démarrage de l'appareil, mais ne le réveille pas. Le temps écoulé inclut toute période pendant laquelle l'appareil était en veille.

  • ELAPSED_REALTIME_WAKEUP : réveille l'appareil et déclenche l'intent en attente une fois que la durée spécifiée s'est écoulée depuis le démarrage de l'appareil.

  • RTC : déclenche l'intent en attente à l'heure spécifiée, mais ne réveille pas l'appareil.

  • RTC_WAKEUP : réveille l'appareil pour déclencher l'intent en attente à l'heure spécifiée.

Exemples d'alarmes de temps réel écoulé

Voici quelques exemples d'utilisation de ELAPSED_REALTIME_WAKEUP :

Réveillez l'appareil pour déclencher l'alarme dans 30 minutes, puis toutes les 30 minutes :

Kotlin

// Hopefully your alarm will have a lower frequency than this!
alarmMgr?.setInexactRepeating(
        AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
        AlarmManager.INTERVAL_HALF_HOUR,
        alarmIntent
)

Java

// Hopefully your alarm will have a lower frequency than this!
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_HALF_HOUR,
        AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);

Réveillez l'appareil pour déclencher une alarme unique (non répétitive) dans une minute :

Kotlin

private var alarmMgr: AlarmManager? = null
private lateinit var alarmIntent: PendingIntent
...
alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
    PendingIntent.getBroadcast(context, 0, intent, 0)
}

alarmMgr?.set(
        AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() + 60 * 1000,
        alarmIntent
)

Java

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() +
        60 * 1000, alarmIntent);

Exemples d'alarmes d'horloge en temps réel

Voici quelques exemples d'utilisation de RTC_WAKEUP.

Réveillez l'appareil pour déclencher l'alarme vers 14h00 et répétez-la une fois par jour à la même heure :

Kotlin

// Set the alarm to start at approximately 2:00 p.m.
val calendar: Calendar = Calendar.getInstance().apply {
    timeInMillis = System.currentTimeMillis()
    set(Calendar.HOUR_OF_DAY, 14)
}

// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr?.setInexactRepeating(
        AlarmManager.RTC_WAKEUP,
        calendar.timeInMillis,
        AlarmManager.INTERVAL_DAY,
        alarmIntent
)

Java

// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);

// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        AlarmManager.INTERVAL_DAY, alarmIntent);

Réveillez l'appareil pour déclencher l'alarme à 8h30 précisément, puis toutes les 20 minutes :

Kotlin

private var alarmMgr: AlarmManager? = null
private lateinit var alarmIntent: PendingIntent
...
alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
    PendingIntent.getBroadcast(context, 0, intent, 0)
}

// Set the alarm to start at 8:30 a.m.
val calendar: Calendar = Calendar.getInstance().apply {
    timeInMillis = System.currentTimeMillis()
    set(Calendar.HOUR_OF_DAY, 8)
    set(Calendar.MINUTE, 30)
}

// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr?.setRepeating(
        AlarmManager.RTC_WAKEUP,
        calendar.timeInMillis,
        1000 * 60 * 20,
        alarmIntent
)

Java

private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);

// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        1000 * 60 * 20, alarmIntent);

Déterminez la précision de votre alarme

Comme décrit précédemment, le choix du type d'alarme est souvent la première étape de la création d'une alarme. Une autre distinction concerne la précision de votre alarme. Pour la plupart des applications, setInexactRepeating() est le bon choix. Lorsque vous utilisez cette méthode, Android synchronise plusieurs alarmes répétées inexactes et les déclenche en même temps. Cela réduit la consommation de la batterie.

Si possible, évitez d'utiliser des alarmes exactes. Toutefois, pour les rares applications qui ont des exigences de temps strictes, vous pouvez définir une alarme exacte en appelant setRepeating().

Avec setInexactRepeating(), vous ne pouvez pas spécifier d'intervalle personnalisé comme vous le pouvez avec setRepeating(). Vous devez utiliser l'une des constantes d'intervalle, comme INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY, etc. Pour obtenir la liste complète, consultez AlarmManager.

Annuler une alarme

Selon votre application, vous pouvez inclure la possibilité d'annuler l'alarme. Pour annuler une alarme, appelez cancel() sur l'Alarm Manager, en transmettant le PendingIntent que vous ne souhaitez plus déclencher. Exemple :

Kotlin

// If the alarm has been set, cancel it.
alarmMgr?.cancel(alarmIntent)

Java

// If the alarm has been set, cancel it.
if (alarmMgr!= null) {
    alarmMgr.cancel(alarmIntent);
}

Déclencher une alarme au redémarrage de l'appareil

Par défaut, toutes les alarmes sont annulées lorsqu'un appareil s'éteint. Pour éviter cela, vous pouvez concevoir votre application de manière à ce qu'elle redémarre automatiquement une alarme récurrente si l'utilisateur redémarre l'appareil. Cela garantit que AlarmManager continuera d'effectuer sa tâche sans que l'utilisateur ait besoin de redémarrer manuellement l'alarme.

Voici la procédure à suivre :

  1. Définissez l'autorisation RECEIVE_BOOT_COMPLETED dans le fichier manifeste de votre application. Cela permet à votre application de recevoir le ACTION_BOOT_COMPLETED diffusé une fois le démarrage du système terminé (cela ne fonctionne que si l'application a déjà été lancée par l'utilisateur au moins une fois) :

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  2. Implémentez un BroadcastReceiver pour recevoir la diffusion :

    Kotlin

    class SampleBootReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            if (intent.action == "android.intent.action.BOOT_COMPLETED") {
                // Set the alarm here.
            }
        }
    }

    Java

    public class SampleBootReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
                // Set the alarm here.
            }
        }
    }
  3. Ajoutez le récepteur au fichier manifeste de votre application avec un filtre d'intent qui filtre l'action ACTION_BOOT_COMPLETED :

    <receiver android:name=".SampleBootReceiver"
            android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"></action>
        </intent-filter>
    </receiver>

    Notez que dans le fichier manifeste, le récepteur de démarrage est défini sur android:enabled="false". Cela signifie que le récepteur ne sera pas appelé, sauf si l'application l'active explicitement. Cela empêche l'appel inutile du récepteur de démarrage. Vous pouvez activer un récepteur (par exemple, si l'utilisateur définit une alarme) comme suit :

    Kotlin

    val receiver = ComponentName(context, SampleBootReceiver::class.java)
    
    context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP
    )

    Java

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

    Une fois le récepteur activé de cette manière, il le restera, même si l'utilisateur redémarre l'appareil. En d'autres termes, l'activation programmatique du récepteur remplace le paramètre du fichier manifeste, même après un redémarrage. Le récepteur restera activé jusqu'à ce que votre application le désactive. Vous pouvez désactiver un récepteur (par exemple, si l'utilisateur annule une alarme) comme suit :

    Kotlin

    val receiver = ComponentName(context, SampleBootReceiver::class.java)
    
    context.packageManager.setComponentEnabledSetting(
            receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
    )

    Java

    ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    PackageManager pm = context.getPackageManager();
    
    pm.setComponentEnabledSetting(receiver,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);

Déclencher des alarmes lorsque l'appareil est en mode Veille prolongée

Les appareils équipés d'Android 6.0 (niveau d'API 23) sont compatibles avec le mode Veille, qui permet de prolonger l'autonomie de la batterie de l'appareil. Les alarmes ne se déclenchent pas lorsque l'appareil est en mode Sommeil. Les alarmes programmées sont reportées jusqu'à ce que l'appareil quitte le mode Sommeil. Si vous devez effectuer des tâches même lorsque l'appareil est inactif, plusieurs options s'offrent à vous :

  • Réglez une alarme exacte.

  • Utilisez l'API WorkManager, conçue pour effectuer des tâches en arrière-plan. Vous pouvez indiquer au système qu'il doit accélérer votre travail pour qu'il se termine le plus rapidement possible. Pour en savoir plus, consultez Planifier des tâches avec WorkManager.

Bonnes pratiques

Chaque choix que vous faites lors de la conception de votre alarme récurrente peut avoir des conséquences sur la façon dont votre application utilise (ou abuse) des ressources système. Par exemple, imaginez une application populaire qui se synchronise avec un serveur. Si l'opération de synchronisation est basée sur l'heure et que chaque instance de l'application se synchronise à 23h, la charge sur le serveur peut entraîner une latence élevée, voire un déni de service. Suivez ces bonnes pratiques pour utiliser les alarmes :

  • Ajoutez de l'aléatoire (jitter) à toutes les requêtes réseau déclenchées par une alarme répétée :

    • Effectuez des tâches locales lorsque l'alarme se déclenche. Le terme "travail local" désigne tout ce qui n'a pas besoin d'un serveur ni des données du serveur.

    • En même temps, planifiez l'alarme contenant les requêtes réseau pour qu'elle se déclenche à un moment aléatoire.

  • Réduisez au maximum la fréquence de vos alarmes.

  • Ne réveillez pas l'appareil inutilement (ce comportement est déterminé par le type d'alarme, comme décrit dans Choisir un type d'alarme).

  • Ne définissez pas une heure de déclenchement plus précise que nécessaire pour votre alarme.

    Utilisez setInexactRepeating() à la place de setRepeating(). Lorsque vous utilisez setInexactRepeating(), Android synchronise les alarmes récurrentes de plusieurs applications et les déclenche en même temps. Cela réduit le nombre total de fois où le système doit réactiver l'appareil, ce qui réduit la consommation de la batterie. Depuis Android 4.4 (niveau d'API 19), toutes les alarmes récurrentes sont des alarmes inexactes. Notez que si setInexactRepeating() est une amélioration par rapport à setRepeating(), il peut toujours submerger un serveur si chaque instance d'une application atteint le serveur à peu près au même moment. Par conséquent, pour les requêtes réseau, ajoutez un peu d'aléatoire à vos alarmes, comme indiqué précédemment.

  • Si possible, évitez de baser votre alarme sur l'heure de l'horloge.

    Les alarmes récurrentes basées sur une heure de déclenchement précise ne sont pas adaptées à la mise à l'échelle. Utilisez ELAPSED_REALTIME si vous le pouvez. Les différents types d'alarmes sont décrits plus en détail dans la section suivante.