AlarmManager sur API19 utilise la méthode setExact () pour définir une alarme exacte.
Moyens exacts -> Si je règle une alarme à 14h01, elle sera déclenchée à 14h01.
Sur la API 23 - Marhsmwallow (6.0), il existe une nouvelle méthode setExactAndAllowWhileIdle (), mais en ce qui concerne la référence, elle n’est pas EXACT car elle ne déclenchera que toutes les minutes et sera inactive mode uniquement toutes les 15 minutes.
Exact! = Toutes les 15 minutes :-)
Alors, comment puis-je obtenir une alarme exacte avec AlarmManager dans 6.0?
Si un utilisateur ajoute un rappel ou un rendez-vous dans l'agenda et souhaite être informé 10 minutes avant l'événement, l'alarme EXACT doit s'afficher 10 minutes avant l'événement. Avec setExactAndAllowWhileIdle (), cela ne semble pas possible.
Lien de référence: http://developer.Android.com/reference/Android/app/AlarmManager.html#setExactAndAllowWhileIdle(int, long, Android.app.PendingIntent)
Alors, comment puis-je obtenir une alarme exacte avec AlarmManager dans la version 6.0?
Vous êtes le bienvenu pour essayez setAlarmClock()
, car, autant que je sache, il n’est pas affecté par le mode Doze. Sinon, AlarmManager
n'est pas une option viable pour vous. Même si votre application figure sur la liste blanche d'optimisation de batterie, cela ne vous aidera pas, car le comportement de AlarmManager
ne changera pas en fonction de la liste blanche.
Vous êtes invités à utiliser GCM, car un message prioritaire devrait vous donner l’occasion d’alerter l’utilisateur. Cela nécessite bien sûr une connectivité réseau.
La seule solution hors connexion dont j'ai connaissance - et que je teste actuellement - consiste à demander à l’utilisateur d’ajouter votre application à la liste blanche d’optimisation de la batterie, puis à utiliser un service de premier plan (pour essayer de conserver votre processus), un ScheduledExecutorService
(for le timing), et un WakeLock
partiel (pour garder la CPU allumée). Ce sera assez dévastateur pour la batterie de l'utilisateur.
L'utilisation de setExactAndAllowWhileIdle () pour une alarme unique se déclenchera exactement à l'heure indiquée, même en mode veille de Doze. Donc, c'est probablement la voie à suivre.
Les problèmes commencent si vous souhaitez répéter l’alarme à une vitesse <15 min (ou définissez-en une autre à moins de 15 min de la dernière), car cela ne fonctionnera pas en mode veille Doze, où de telles alarmes sont forcées aux 15 minutes suivantes ou sont exécutées lorsque la maintenance en attente commence, ce qui dure environ dix minutes, après 1 heure, puis après 2 heures supplémentaires, puis après 4 heures supplémentaires, etc.
- MODIFIER -
À compter d’aujourd’hui 17 novembre, Dianne Hackborn écrit dans les commentaires de cet article : "Pour ce que cela vaut, le temps minimum entre deux alarmes inactives passera à 9 minutes à un moment donné ( même sur les appareils exécutant les versions actuelles de Marshmallow). "
Cela ne change rien fondamentalement cependant.
J'ai trouvé que jusqu'à présent la meilleure option consiste à utiliser un SyncAdapter qui étend AbstractThreadedSyncAdapter. Je le programme pour qu'il continue à exécuter mon code automatiquement à l'intervalle requis:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
ContentResolver.addPeriodicSync(account, AUTHORITY, settingsBundle, syncInterval);
J'essayais de créer un système d'automatisation fonctionnant en arrière-plan. Ma gamme de fréquence était entre 1-15 minutes. Mon souhait n'était pas d'utiliser un service de premier plan. En regardant le nom de la méthode "setExactAndAllowWhileIdle", j'ai pensé que oui, il est prudent d'utiliser des alarmes uniques, en planifiant la suivante lorsque vous avez terminé.
Cependant, je ne pouvais pas trouver un moyen d'exécuter du code en mode assoupi avec des alarmes exécutées plus souvent que 15 minutes. Au lieu de cela, je choisis de démarrer un service de premier plan lorsque le mode assoupi est activé et d’arrêter ce service de premier plan lorsque le téléphone se réveille. L'utilisateur ne verra pas votre notification de premier plan lorsqu'il utilisera son téléphone. Je me fiche de ceux qui sont en mode assoupi.
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(intent.getAction().equals("Android.os.action.DEVICE_IDLE_MODE_CHANGED")){
if (pm.isDeviceIdleMode()) {
//startAutomationForegroundService();
} else {
//stopAutomationForegroundService();
return;
}
AutomationReceiver.completeWakefulIntent(intent);
return;
}
}
Vous devez enregistrer le filtre d'intention "Android.os.action.DEVICE_IDLE_MODE_CHANGED" dans votre récepteur WakefulBroadcast. Le soin de le mettre en manifeste peut ne pas aider.