web-dev-qa-db-de.com

setExactAndAllowWhileIdle - ist nicht exakt als Entwicklerreferenz

AlarmManager auf API19 hat die Methode setExact (), um einen genauen Alarm einzustellen.

Genau bedeutet -> Wenn ich einen Alarm auf 14:01 Uhr eingestellt habe, wird er um 14:01 Uhr ausgelöst

In API 23 - Marhsmwallow (6.0) gibt es eine neue Methode setExactAndAllowWhileIdle (), die sich jedoch nicht auf die Referenz bezieht, da sie nur jede Minute auslöst und im Leerlauf läuft Nur Modus alle 15 Minuten.

Genau! = Alle 15 Minuten :-)

Wie kann ich mit AlarmManager in 6.0 einen genauen Alarm erreichen?

Wenn ein Benutzer eine Erinnerung oder einen Kalendertermin hinzufügt und 10 Minuten vor dem Ereignis informiert werden möchte, sollte der Alarm EXACT 10 Minuten vor dem Ereignis angezeigt werden. Mit setExactAndAllowWhileIdle () scheint dies nicht möglich zu sein.

Referenzlink: http://developer.Android.com/reference/Android/app/AlarmManager.html#setExactAndAllowWhileIdle(int, long, Android.app.PendingIntent)

42
chrisonline

Wie kann ich also mit AlarmManager in 6.0 einen genauen Alarm erzielen?

Sie können gerne versuchen Sie setAlarmClock() , da AFAIK vom Doze-Modus nicht betroffen ist. Andernfalls ist AlarmManager keine praktikable Option für Sie. Selbst wenn Ihre App auf der Whitelist für die Batterieoptimierung steht, ist dies nicht hilfreich, da sich das Verhalten von AlarmManager nicht auf der Whitelist-Liste ändert.

Sie können GCM gerne verwenden, da eine Nachricht mit hoher Priorität Ihnen die Möglichkeit geben sollte, den Benutzer zu warnen. Dies erfordert natürlich eine Netzwerkverbindung.

Die einzige Offline-Lösung, die ich kenne - und die ich gerade teste - besteht darin, dass der Benutzer Ihre App zur Whitelist für die Batterieoptimierung hinzufügt und dann einen Vordergrunddienst (um zu versuchen, Ihren Prozess aufrecht zu erhalten), eine ScheduledExecutorService (für das Timing) und eine partielle WakeLock (um die CPU eingeschaltet zu lassen). Dies wird für die Batterie des Benutzers ziemlich verheerend sein.

19
CommonsWare

Die Verwendung von setExactAndAllowWhileIdle () für einen einmaligen Alarm wird zu gegebener Zeit auch im Doze-Ruhezustand exakt ausgelöst. Das ist also wahrscheinlich der Weg zu gehen.

Probleme beginnen, wenn Sie den Alarm mit einer Geschwindigkeit von <15 min wiederholen möchten (oder einen anderen als <15 min vom letzten Alarm entfernt einstellen), da dies im Doze-Ruhezustand nicht funktioniert Solche Alarme werden auf die nächsten 15 Minuten gezwungen oder sie werden ausgeführt, wenn die Wartungsarbeiten im Leerlauf beginnen. Dies geschieht zunächst nach etwa 1 Stunde, dann nach weiteren 2 Stunden, dann nach weiteren 4 Stunden und so weiter.

- EDIT -

Ab dem 17. November schreibt Dianne Hackborn in den Kommentaren von diesem Beitrag : "Die Mindestzeit zwischen Leerlaufalarmsätzen wird sich relativ bald auf 9 Minuten ändern ( sogar auf Geräten, auf denen die aktuellen Marshmallow-Builds ausgeführt werden). "

Dies ändert jedoch nichts grundlegend.

8
sec_aw

Hier ist meine Diskussion mit Ian Lake auf Google+!

setExactAndAllowWhileIdle () ist genau und sollte funktionieren .. Die Zeitspanne von 15 Minuten ist falsch im Java-Dokument

 enter image description here

6
chrisonline

Ich habe festgestellt, dass die beste Option bisher die Verwendung eines SyncAdapter ist, der AbstractThreadedSyncAdapter erweitert. Ich plane es so ein, dass mein Code automatisch im erforderlichen Intervall ausgeführt wird: 

ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
ContentResolver.addPeriodicSync(account, AUTHORITY, settingsBundle, syncInterval);
1
Hashim Akhtar

Ich habe versucht, ein Automatisierungssystem zu erstellen, das im Hintergrund läuft. Mein Frequenzbereich lag zwischen 1-15 Minuten. Mein Wunsch war es, keinen Vordergrundservice zu nutzen. Als ich den Namen der Methode "setExactAndAllowWhileIdle" betrachtete, dachte ich, dass es sicher ist, einmalige Alarme zu verwenden, und den nächsten zu planen, wenn er fertig ist.

Ich konnte jedoch keinen Weg finden, um Code im Doze-Modus auszuführen, wobei Alarme häufiger als 15 Minuten ausgeführt werden. Stattdessen möchte ich einen Vordergrunddienst starten, wenn der Doze-Modus aktiviert wird, und den Vordergrunddienst beenden, wenn das Telefon aufwacht. Der Benutzer wird Ihre Vordergrundbenachrichtigung während der Verwendung seines Telefons nicht sehen. Ich interessiere mich nicht besonders für diejenigen im Dösenmodus.

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

Sie müssen den Absichtsfilter "Android.os.action.DEVICE_IDLE_MODE_CHANGED" in Ihrem WakefulBroadcastReceiver registrieren. Sorgfalt, wenn man es manifestiert, kann nicht helfen.

0