setExact beim AlarmManager noch immer nicht ganz genau exakt?

  • Antworten:11
  • OffenNicht stickyNicht beantwortet
  • Forum-Beiträge: 98

09.03.2015, 22:40:16 via Website

Hallo Forum,
abermals habe ich eine Frage zum AlarmManager und der neuen Methode setExact.

Bei meinem Nexus 5 ( Android 5.0.1 ) habe ich das Phänomen festgestellt, dass setExact innerhalb einer Stunde plötzlich um bis zu 2 Minuten vom Ausgangspunkt abweichen kann.

Bsp:

Alarm um 21:20:00 passt auf ca. 7 Sekunden genau ( 21:00:07 )
Alarm um 21:37:00 passt auf ca. 7 Sekunden genau ( 21:37:07 )
Alarm um 22:20 ist bereits um 30 Sekunden zu spät
Alarm um 22:37 teilweise bis zu 2 Minuten zu spät

Laut Doku, wenn ich sie richtig interpretiere ist auch setExact nicht immer genau, wie es einst setRepeating aber war!
Hier ein Auszug:

This method is like set(int, long, PendingIntent), but does not permit the OS to adjust the delivery time. The alarm will be
delivered as nearly as possible to the requested trigger time.

Ist das so richtig interpretiert oder hab ich einfach ein Problem mit meinem Nexus?

Wenn es stimmen sollte, was ich "lese", dann muss ich wohl mit einem Intentservice jede Minute überprüfen, ob ein Alarm wieder ausgelöst werden sollte.
Leider bin ich mir noch im unklaren, wie ich das Service stoppen kann, wenn der User absichtlich oder unabsichtlich die App geschlossen haben sollte. Eventuell würde ein stopSelf() Aufruf in der onDestroy() - Methode funktionieren?

Ich danke Euch schon vielmals für Eure Hilfe!

lG

Antworten
  • Forum-Beiträge: 1.904

10.03.2015, 15:49:30 via App

Ich verstehe das so, dass nur versucht wird, so nah wie möglich an der Zeit den Alarm auszulösen. Also nicht genau.

http://stackoverflow.com/a/27589596 kann aber auch sein, dass die log Ausgabe verzögert ist?! Keine Ahnung

— geändert am 10.03.2015, 15:52:33

Wenn dir mein Beitrag gefällt, kannst dich einfach mit dem 👍 "Danke"-Button auf der Website dieses Forums bedanken. 😀

Why Java? - Because I can't C#

Antworten
  • Forum-Beiträge: 98

10.03.2015, 15:53:31 via Website

Hallo,
genauso habe ich es auch verstanden.

Dann muss ich um den Zeitpunkt exakt zu treffen mir ein IntentService basteln u. darin dann das Ganze abarbeiten!

Danke Dir vielmals!

lG

Antworten
Gelöschter Account
  • Forum-Beiträge: 464

10.03.2015, 17:13:30 via App

Hast du dir mal die Daten des Calendars, womit du den Alarmmanger setzt, ausgeben lassen? Ich hatte nämlich dasselbe Problem (auch mit set Excat) und habe dann später bemerkt, dass die Daten ein bisschen anders waren. Nach dem Ändern kommt der Alarm nun bei mir auf die Sekunde genau. (Mein Testgerät ist auch ein Nexus 5 mit Lollipop).

Du hast zum Apfel gegriffen? Gott möge dir verzeihen.

Antworten
  • Forum-Beiträge: 98

10.03.2015, 17:22:09 via Website

Hallo,
nein, sowas habe ich noch nicht versucht.
Ich berechne mir schon im vorhinein zu welcher Tageszeit welcher Alarm gesetzt werden soll und dann wird das in einem Dictionary durchgelaufen und abgearbeitet.

Das Dic. sieht so aus:

"Nachricht": 17:30 ( Uhrzeit ist in Millisekunden umgerechnet, hier nur zur Lesbarkeit anders geschrieben! )
"Nachricht": 17:45
"Nachricht": 18:00
 usf.

Sobald das Programm zu einem setExact kommt, wird mittels pollFirstEntry() der erste Eintrag genommen und mittels setExact gesetzt u. so geht es dann immer weiter!

Somit müsste der Calendar - Eintrag eigentlich stimmen, weil ich mir die richtigen! Werte vom Dictionary nehme.

Oder sehe ich etwas falsch?

Danke Dir vielmals!

lG

Antworten
  • Forum-Beiträge: 98

11.03.2015, 08:44:00 via Website

Hallo,
ich habe mein Programm nun auf ein IntentService umgeschrieben ohne setExact mehr zu verwenden (setRepeating bleibt weiterhin für Android Version unter 4.3 bestehen )und nun scheint es nach den ersten Tests wieder zu funktionieren.
Wenn ich vorher diese Teststellung hatte:

08:02 Nachricht
08:19 Nachricht
09:02 Nachricht
09:19 Nachricht

hatte ich bereits beim Versand um 08:19 eine Abweichung von mindestens 7 Sekunden. Mit dem Intentservice ist es nun so, dass die Nachricht regelmässig ( derzeit noch! ) 4 Sekunden nach 09:02, 09:19 eintrifft, also perfekt für mich!

Danke für Deine Hilfe!

Antworten
  • Forum-Beiträge: 16

15.10.2015, 10:54:41 via Website

Hallo,

ich grabe das Thema noch einmal aus weil ich ein wenig am verzweifeln bin.

Ich versuche einen Timer zu realisieren der minutengenau arbeiten sollte.
Vor API19 war ja alles ok. Da hat setRepeating() vom AlarmManager einwandfrei funktioniert.

Mit KitKat bin ich wie man es so in den Dokus findet auf >> getAlarmManager(context).setExact(AlarmManager.RTC_WAKEUP, alarmTimeMillis, pi) << umgestiegen.

Aber vor allem mit API21 und 22 (und auch nur bei einigen Geräten wie das Samsung S6 oder Note 4) scheint sich hier Android zu weigern pünktlich zu arbeiten.
Wenn die Energiesparfunktionen aktiv sind wird sogar das RTC_WAKEUP ignoriert und manchmal garnicht (also erst nach einschalten des Displays) und manchmal erst mit bis zu 5 Minuten Verspätung der BroadcastReceiver gefeuert......

Einen permanent laufenden IntentService zu bauen finde ich nicht sehr sinnvoll. Ich habe zwar einen IntentService der den Timer berechnet und startet ( mit setExact() ) aber sobald der Timer registiert ist wird der Service beendet......
Funktionieren tut alles soweit. Nur ist der Timer nicht auf die Minute genau, was für meinen Anwendungsfall aber notwendig ist!

Ich verzweifel noch daran wie ich Android hier zu einer Einhaltung der Pünktlichkeit zwingen kann ;-)
Insbesondere die Wecker der betreffenden Smartphones müssen es ja irgend wie hinbekommen trotz Energiesparfunktion pünktlich zu klingeln...

P.S. Mit dem Timer wird ebenfalls ein Hintergrundprozess (AlarmReceiver) gestartet der lediglich eine SMS verschickt ohne dabei das Display einzuschalten oder eine Activity zu starten.....

Antworten
  • Forum-Beiträge: 98

15.10.2015, 17:01:09 via Website

Hallo,
ich hatte anfangs auch Probleme mit setExact, da dieser nur beim ersten Mal reagiert hat, danach erst wieder, wenn man das Handy eingeschalten hat. Ich vermute, dass ich das über einen Intentservice realisieren hätte sollen/müssen.
Nun wird bei mir alles mit einem IntentService eben gemacht, funktioniert einwandfrei und genau.

Was Du vermutlich machen musst, damit es minutengenau ist, wäre folgendes:

Berechne die Zeit bis zum nächsten Aufwecken, Bsp:

Jetzt aktiviert = 23:11 plus Datum, umrechnen in Millisekunden
09:00 Aufwecken, dasselbe wie oben

Dann gehst du her und sagst, dass das Handy bereits 2 Minuten vor dem eigentlichen Zeitpunkt aufwachen soll, also 08:58 ( = 120000 ms abziehen! ).
Und ab diesem Zeitpunkt könntest Du den Intentservice mit Thread.sleep(1000) ( = 1 sek. ) schlafen legen und wenn es dann soweit ist, dann wird der Alarm oder was immer Du machen möchtest abgefeuert.
So habe ich es getan und die Batterie wird damit auch nicht belastet und des weiteren wird der Alarm Sekunden genau abgesetzt.
Auch der AlarmManager.setRepeating arbeitet nicht anders.

Hoffe, dass Dir diese Lösung weiter hilft?

lG

Antworten
  • Forum-Beiträge: 16

15.10.2015, 18:21:05 via Website

Hmmm... und wie sage ich ihm das er aufwachen soll?
Ebenfalls mit einem setExact der um diese vermeintlichen 5 Minuten voraus eilt?

Oder gibt es hierfür noch eine andere Funktion?
Woran ich grade forsche ist, ob es wirklich immer 5 Minuten sind....
Das schwierige daran ist das es bei meinen Geräten problemlos funktioniert. Nur bei anderen vereinzelten Nutzern nicht.
Das macht das debuggen unheimlich schwer ;-)

Antworten
  • Forum-Beiträge: 98

15.10.2015, 18:36:30 via Website

Du könntest es mit setExact probieren, was ich allerdings ja einst verworfen habe und jetzt nur mal testweise durchspielen will, ob es mit einem IntentService dann auch funktioniert.
So habe ich mir halt dann damals ein eigenes setExact geschrieben!

Um das Handy aufzuwecken ( Display einzuschalten zB ) könntest Du den PowerManage aktivieren bzw. einen Broadcast senden und dann im Broadcast darauf reagieren.
Eventuell musst du noch berücksichtigen, dass der User deine App in den Hintergrund stellt, dann solltest Du die App zuerst in den Vordergrund bringen und dann das Display einschalten.
So würde ich das machen.
Weiters wäre noch zu berücksichtigen, dass die App ja geschlossen werden kann, dann musst du die App auf NotificationBar oder so stellen.

Antworten
  • Forum-Beiträge: 16

15.10.2015, 18:47:32 via Website

Nun es ist ja zum Glück keine View die ich aktualisieren muss sondern ein einfacher LocalService der vom BroadcastRevceiver des setExact ausgeführt wird.
Alles was passiert passiert im Hintergrund ohne Display und irgendwelche sichtbaren Folgen.

Theoretisch könnte ich meinen LocalService auch mit sleep entsprechend lange einfrieren aber ich weiß nicht ob das so Sinn der Sache ist.....

Antworten
  • Forum-Beiträge: 98

15.10.2015, 18:54:22 via Website

Also ich habe mein IntentService so lange mit sleep eingefroren und erst 1 oder 2 Minuten bevor es losgehen sollte, aufgeweckt.
Nicht wirklich anders macht das ein setExact ( ich habe einmal den Code mir zu setExact durchgelesen, aber ich kann es nicht mehr genau sagen ).

Ich würde es so versuchen, so macht es so gut wie ein jeder, was ich weiss:

Antworten

Empfohlene Artikel