web-dev-qa-db-fra.com

Comment faire fonctionner Alarm Manager lorsque Android 6.0 en mode Doze?

Je suis développeur de deux applications de réveil sur Google Play. J'essaie de les faire fonctionner avec Android 6.0. Cependant, le mode Doze fait en sorte qu'ils ne sonnent pas. Je les mets sur la liste blanche, je mets une icône de notification au premier plan, je Je ne sais pas quoi faire d'autre - en mode Doze, les alarmes du gestionnaire d'alarmes sont toujours ignorées. L'application Horloge (qui est une application Google Play plutôt qu'une application AOSP), cependant, est différente. Lorsque l'alarme est activée sur l'application Clock, "adb deviceidle step" lira toujours "active" et jamais "inactive", "idle_pending" ou toute autre chose.

Android triche ici, donnant plus de puissance à sa propre application, alias. "Tirer une pomme"? Est-ce que toutes les applications de réveil sur Google Play sont sur le point de devenir non fonctionnelles? sont des applications de qualité qui ont chacune pris un an de temps de développement à temps partiel et sont de grandes sources de revenus pour moi. Tout indice sur la façon dont je pourrais les faire fonctionner serait d'une grande aide.

Définition de l'intention AlarmManager:

        Intent intent = new Intent(context, ReceiverAlarm.class);
        if (Android.os.Build.VERSION.SDK_INT >= 16) {
            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        }
        amSender = PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_CANCEL_CURRENT); //FLAG_CANCEL_CURRENT seems to be required to prevent a bug where the intent doesn't fire after app reinstall in KitKat
        am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, scheduleToTime+1, amSender);

et la classe ReceiverAlarm:

public class ReceiverAlarm extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
    if (wakeLock == null) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Theme.appTitle);
        wakeLock.acquire();
    }
    X.alarmMaster.startRingingAlarm(true);
}

et les parties pertinentes de la méthode X.alarmMaster.startRingingAlarm ():

    if (wakeLock == null) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Theme.appTitle);
        wakeLock.acquire();
    }

    if (screenWakeLock == null) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        screenWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, Theme.appTitle+" scr");
        screenWakeLock.acquire();
    }

    Intent alarmIntent = new Intent(Intent.ACTION_VIEW);
    alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    alarmIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    alarmIntent.setClass(context, ActivityAlarmAlarm.class);

    context.startActivity(alarmIntent);

Certaines des méthodes ont été collées en ligne pour une meilleure lisibilité.

47
user1908060

Doze et App Standby changent définitivement le comportement en ce qui concerne les alarmes et les réveils, mais ils ne sont certainement pas la fin du monde pour vous!

Avez-vous essayé d'utiliser la méthode setAlarmclock() au lieu de set()? Il est spécialement conçu pour les réveils et peut être capable de couper la somnolence. Il existe quelques commandes adb que vous pouvez utiliser pour mettre manuellement un téléphone en mode veille ou application: https://developer.Android.com/preview/features/power-mgmt.html

Si cela n'est pas en mesure de réveiller votre application, il existe la méthode infaillible setExactAndAllowWhileIdle() est conçue pour réveiller le téléphone de somnoler, quoi qu'il arrive. Dans le pire des cas, vous pouvez réactiver votre application avec cette méthode et utiliser le réveil pour planifier la prochaine alarme.

Une autre page mérite d'être lue est cet article de blog avec son organigramme pour le travail de fond et les alarmes: https://plus.google.com/+AndroidDevelopers/posts/GdNrQciPwqo

34
ccpmark

Mettre l'application en liste blanche autorise uniquement le réseau en mode somnolence. AlarmManager n'est pas affecté par la liste blanche.

Pour la méthode setExactAndAllowWhileIdle (), veuillez vérifier la description ci-dessous du SDK. Il ne réveillera pas le téléphone de la somnolence.

Lorsque l'alarme est envoyée, l'application est également ajoutée à la liste blanche temporaire du système pendant environ 10 secondes pour permettre à cette application d'acquérir d'autres verrous de réveil pour terminer son travail.

2
Wonil