Akkuverbrauch enorm gross bei GPS

  • Antworten:10
Michael H
  • Forum-Beiträge: 127

03.07.2012, 08:44:19 via Website

Hallo zusammen

Meine App soll im Hintergrund (Service) in einem zuvor vorgegebenen Intervall (meist ca. 30sek.) GPS-Koordinaten einsammeln. Ich habe das ganze mit einem requestLocationUpdates(provider,mintime,mindistance,listener) umgesetzt. Jedoch habe ich gemerkt, dass diese Methode meine mintime gewissermassen ignoriert. Nun pick ich mir nur diejenigen raus, welche ich schlussendlich dann auch brauche (alle 30sek.). Nun nach ein paar Testversuchen sah ich schnell dass das ganze richtig heftig an meinem Akku saugt, was natürlich nicht Sinn und Zweck der ganzen Sache ist. Jetzt meine Frage: Hat jemand bereits Erfahrungen mit GPS gemacht und kann mir vielleicht 2,3 Tipps dazu geben?

Gruss Michi

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

03.07.2012, 10:35:02 via Website

Ich habe Apps mit GPS im Markt (Tankbuch Mobil Pro, GaCoMo, ...) und kann den Akku-Verbrauch bedingt bestätigen. Allerdings gibt es viele Dinge die ich in dem Zusammenhang überprüfen würde:

* Welche Nutzungsart? Fußgänger, Radfahrer, Autofahrer, Segelflieger, ...?

* Was willst Du machen? Strecke aufzeichnen, Geschwindigkeit messen, Augmented Reality App für Fußgänger, ...?

* Die beiden vorgenannten bestimmen in gewissem Masse die Intervalle in denen man sich die Updates liefern lässt? Desto höher die Frequenz, desto mehr Arbeit in der App, desto größer der Akku-Verbrauch. Am Grundumsatz des GPS Subsystems kannst Du nichts verändern - Du kannst nur Deine App in Sachen GPS schlanker machen. Eine typische mittlere GPS Genauigkeit liegt irgendwo bei 7m - das sind so meine Erfahrung mit meinen GPS Sportuhren die mir auch die Satelliten grafisch anzeigen. Meiner Meinung nach hat es per se keinen Sinn unter 7m zu gehen. Wenn Du auf 30sec gehst musst Du auch die Distanz erhöhen denn "whatever comes first" gilt beim LocationManager. Beispiel: Streckenaufzeichnung: Für einen Autofahrer kannst Du getrost auf 1000m und 60sec setzen. Ein Fußgänger kann je nach Nutzungsart auf 7m/2sec gesetzt werden. Du verstehst was ich meine? Das ist der erste Teil auf den Du Einfluss hast.

* Wenn die Location Updates in Deine App kommen beginnt der zweite Teil auf den Du Einfluss hast. Was machst Du dann? Guck das Du so schnell wie möglich aus dem onLocationChanged() raus kommst.

Ich will Dir keine Hoffnung machen. Der Teil den Du beeinflussen kannst ist relativ gering - aber auch darin kann man Böcke schießen. Und wenn man in einer GPS Session ein paar tausend Mal durch den onLocationChanged() rennt summiert sich das.

— geändert am 03.07.2012, 10:36:27

Antworten
Michael H
  • Forum-Beiträge: 127

03.07.2012, 11:20:42 via Website

Es ist immer schön auf einen Kenner der Materie zu treffen! :) Vielen Dank

Die Nutzung der App ist für PW/LKW fahrer gedacht. Es soll im nachhinein anhand der gesammelten Koordinaten die gefahrene Spur aufgezeichnet werden können. Du hast was von 1000m und 60sec geschrieben. Was ist aber wenn sich der Fahrer in einer Stadt befindet? Dann kann ein Kilometer oder eben 60sec ziemlich weit/lang sein, nicht?

Was mir auch noch nicht klar ist, von wo soll das Gerät wissen dass es jetzt z.B. 7m von der letzten Koordinate entfernt ist, ohne ständig Koordinaten zu sammeln?

Ich habe bis jetzt immer mit 30sec und 0m getestet und dachte somit er ignoriert die Meter und holt jeweils alle 30sec eine Koordinate. Die Tests haben jedoch ergeben, dass das Gerät im Sekundentakt GPS Koordinaten empfängt... Deine Aussage: "whatever comes first" erklärt jetzt einiges :) Ich kann mir vorstellen, dass es an dem gelegen hat, wieso ich bereits nach ein paar Stunden kein Saft mehr hatte..?

Ich werde das ganze mal testen und mich wieder melden...

Vielen Dank für deine Mühe, Harald!

Antworten
Michael H
  • Forum-Beiträge: 127

03.07.2012, 12:03:54 via Website

Habe das ganze mal getestet. Nun musste ich feststellen wenn ich die minTime auf 30000 (30sec) und minDistance auf 1000m stelle, und mich dann im Umkreis von ein paar wenigen Metern bewege gibt er mir nach 30sec keine Koordinate, obwohl die minTime abgelaufen wäre, was ja bedeuten würde das "whatever comes first" funktioniert irgendswie nicht?

Was mir beim testen auch noch aufgefallen ist, der Satellit im Phone oben in der Bar ist permanent an, was ja bedeutet er holt permanent GPS Koordinaten?

Gruss

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

03.07.2012, 12:20:01 via Website

Michael H
Was mir auch noch nicht klar ist, von wo soll das Gerät wissen dass es jetzt z.B. 7m von der letzten Koordinate entfernt ist, ohne ständig Koordinaten zu sammeln?

Ah, Du verwechselst da etwas. Der LocationManager hat jederzeit Kenntnis wo er sich befindet - sofern die Subsysteme aktiviert sind. Du teilst mit requestLocationUpdates() lediglich mit das Du in den genannten Intervallen informiert werden möchtest.

Beispiel: Deine App und eine Navigations-App sind parallel aktiv. Es gibt nur einen LocationManager der seine Position permanent bestimmt. Dieser pflegt, einfach ausgedrückt, eine Liste der Apps die LocationUpdates "requested" haben. Ist irgendeiner der Intervalle der registrierten Apps abgelaufen dann wird der onLocationChanged() an diese App übermittelt - mehr nicht.

Michael H
Was ist aber wenn sich der Fahrer in einer Stadt befindet? Dann kann ein Kilometer oder eben 60sec ziemlich weit/lang sein, nicht?

Klar - wenn er nicht im Stau oder an der Ampel steht ;-) Dann zieht nämlich der Zeit-Intervall und nicht der Distanz-Intervall. Wie gesagt "whatever comes first". Die jeweilige Nutzungsart legt die Intervalle fest. Was soll die App denn machen? Diese Frage musst Du Dir stellen und basierend darauf die Intervalle intelligent setzen.

Ich registriere mich grundsätzlich für 2sec/7m <psst, nicht weiter erzählen>. Ich merke mir immer die letzte Location und aggregiere Entfernung und Zeit mit jedem LocationUpdate. Anschließend prüfe ich ob mit den Summen die vom Benutzer eingestellten Entfernungen oder Zeiten überschritten wurden. Ist das der Fall dann wird die Datenbank aktualisiert und die Summen werden für den nächsten Zyklus auf 0 gesetzt. Anschließend jage ich Broadcasts an interessierte Aktivities raus und gut ist (mein LocationManager Kram liegt immer in einem Service). Das hat Vor- und Nachteile: So ist die Karte während der Aufzeichnung immer aktuell. Wird die Karte später mal aus der Datenbank gezeichnet so hat sie nur die vom Benutzer eingestellten Genauigkeiten. Ich denke das ist ein guter Kompromiss.

Wie gesagt, Deine App ist nur ein kleiner Teil des Ganzen. Die Möglichkeiten der Akku Schonung sind, von den erwähnten Schnitzern mal abgesehen, marginal. Guck das Deine App möglichst schnell und ohne großes Brimborium aus dem onLocationChanged() rauskommt. Mehr kannst Du nicht machen ... und hoffen das Dein Benutzer nicht parallel Musik hört, eine Navi Software laufen lässt, und, und, und, ...


1private double intervallEntfernung;
2private long intervallZeit;
3private Location locationPrevious;
4private double summeEntfernung;
5
6@Override
7public void onLocationChanged(Location location) {
8
9 if (location != null && (locationPrevious == null || location.getLatitude() != locationPrevious.getLatitude() || location.getLongitude() != locationPrevious.getLongitude())) {
10 double entfernung = 0.0;
11 long zeitDiff = 0;
12
13 if (locationPrevious != null) {
14 entfernung = GeoTools.latLonDistance(locationPrevious.getLatitude(), locationPrevious.getLongitude(), location.getLatitude(), location.getLongitude());
15 zeitDiff = location.getTime() - locationPrevious.getTime();
16
17 intervallEntfernung += entfernung;
18 summeEntfernung += entfernung;
19
20 intervallZeit += zeitDiff;
21 summeZeit += zeitDiff;
22 }
23
24 if (intervallEntfernung > MyPreferenceActivity.getEntfernungsIntervall() || intervallZeit > (MyPreferenceActivity.getAufzeichnungsIntervall() * 1000)) {
25 // Neue Location in Datenbank eintragen, bisherige Summen updaten
26
27 intervallEntfernung = 0.0;
28 intervallZeit = 0;
29 }
30
31 Intent intent = new Intent();
32 intent.putExtra("LATITUDE", location.getLatitude());
33 intent.putExtra("LONGITUDE", location.getLongitude());
34 intent.putExtra("SPEED", location.getSpeed());
35 intent.putExtra("SUMMEENTFERNUNG", summeEntfernung);
36
37 intent.setAction(EineAktivitaet.MyBroadcastReceiver.TAG);
38 sendBroadcast(intent);
39
40 intent.setAction(EineAndereAktivitaet.MyBroadcastReceiver.TAG);
41 sendBroadcast(intent);
42
43 locationPrevious = location;
44 }
45}

— geändert am 03.07.2012, 12:22:47

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

03.07.2012, 12:26:34 via Website

Ahem, ich habe gerade noch mal nachgeschaut. Ich könnte schwören das die Doku geändert wurde. Das AND habe ich bisher noch nie gesehen. Das gibt's doch nicht.

If it is greater than 0 then the location provider will only send your application an update when the location has changed by at least minDistance meters, AND at least minTime milliseconds have passed.

Sorry, vergiss mein Geschwätz über das "whatever comes first".

Antworten
Michael H
  • Forum-Beiträge: 127

03.07.2012, 13:41:35 via Website

Ah okey das mit dem LocationManager ist mir klar. Vielen Dank
Nur das AND macht bei mir kein Sinn! Denn ich habe jetzt eingestellt 2m und 30sec. Am Anfang kamen 3 Koordinaten im Sekundentakt und anschliessend eineinhalb min keine mehr... habe das langsam das Gefühl das ganze funktioniert nicht so wie die Doku behauptet...

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

03.07.2012, 15:02:38 via Website

Ich habe mir nochmal die Doku komplett durchgelesen - nur um zu prüfen ob ich in meinen Apps etwas ändern muss. Der wirklich wichtige Text ist dieser:

The update interval can be controlled using the minTime parameter. The elapsed time between location updates will never be less than minTime, although it can be more depending on the Location Provider implementation and the update interval requested by other applications.

Choosing a sensible value for minTime is important to conserve battery life. Each location update requires power from GPS, WIFI, Cell and other radios. Select a minTime value as high as possible while still providing a reasonable user experience. If your application is not in the foreground and showing location to the user then your application should avoid using an active provider (such as NETWORK_PROVIDER or GPS_PROVIDER), but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) or greater. If your application is in the foreground and showing location to the user then it is appropriate to select a faster update interval.

The minDistance parameter can also be used to control the frequency of location updates. If it is greater than 0 then the location provider will only send your application an update when the location has changed by at least minDistance meters, AND at least minTime milliseconds have passed. However it is more difficult for location providers to save power using the minDistance parameter, so minTime should be the primary tool to conserving battery life.

Da kommt relativ häufig das Wort "however" vor. Das zeigt mir, und so habe ich das auch in den letzten Jahren verstanden, das die Request-Parameter nicht 100% erfüllt werden. Genauso wie Broadcasts auch mal geschlabbert werden können wird das mit LocationUpdates auch so sein. Das ist halt ein Mobil-System. Alle Anwendungen müssen halt mit allen Unwägbarkeiten klar kommen - bis hin zum Abschuss und automatischen Neustart.

Da ich nicht alle LocationUpdates in die Datenbank schreibe (ich aggregiere, siehe oben) kann ich leider nicht die Positionsangaben und Ihre Abstände/Zeiten in der DB prüfen - wäre doch mal eine nette Analyse.

Antworten
Michael H
  • Forum-Beiträge: 127

04.07.2012, 08:18:28 via Website

Danke Harald für die Recherchen!

Die Methoden requestLocationUpdates(...) sind ab API Level 9 gültig. Jedoch mein Testgerät (2.3.6) ignoriert diese Parameter völlig und sammelt GPS Koordinaten nach belieben ein (mal 3 kurz hintereinander, dann wieder eine Minute keine usw..), keine Ahnung wieso!
Für alle die mit dem requestLocationUpdates kämpfen, möchte ich meine alternative Lösung hier reinhacken:

Ich habe nun die requestSingleUpdate() Methode für das Aufsammeln verwendet. Da diese Methode nur eine Koordinate sammelt und sich dann wieder verabschiedet, setze ich einfach einen Timer mit dem GPS intervall, der die requestSingleUpdate() nach der abgelaufenen Zeit wieder neu setzt. Dies funktioniert bis jetzt wunderbar. Auch die Akkuprobleme sind um die Hälfte geschrumpft!

Wer noch eine bessere variante bezüglich des Timers hat, bitte melden... :)

Gruss Michi

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

04.07.2012, 08:44:10 via Website

Michael H
Die Methoden requestLocationUpdates(...) sind ab API Level 9 gültig.

Das ist nicht richtig. Ich verwende immer diesen und der ist seit API Level 1 dabei:

1requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)


Die von Dir verwendeten requestSingleUpdate() sind hingegen erst seit API Level 9 dabei.

Wenn es für Dich klappt um so besser. Laut Doku wird mit jedem SingleRequest gefixt - es dauert also seine Zeit bis der Request erfüllt werden kann. Wenn das bei Dir nicht so ist: noch besser.

Antworten
Michael H
  • Forum-Beiträge: 127

04.07.2012, 09:11:01 via Website

Oh falsch geschaut! Sorry...

Ja der fix dauert ca. eine halbe Sekunde. Nachher ist das GPS Symbol oben nicht mehr aktiv bis die nächste Koordinate ansteht. Ich werds noch ein bisschen testen, und falls negatives auffällt werde ich mich hier wieder melden...

Nochmals vielen Dank für deine Mühe!

Antworten