Ich suche nach einer Möglichkeit, alle n Minuten ein Hintergrund-Standort-Update in meiner iOS-Anwendung zu erhalten. Ich verwende iOS 4.3 und die Lösung sollte für iPhones ohne Jailbreak funktionieren.
Ich habe folgende Optionen ausprobiert / in Betracht gezogen:
CLLocationManager startUpdatingLocation/startMonitoringSignificantLocationChanges
: Dies funktioniert erwartungsgemäß im Hintergrund, basierend auf den konfigurierten Eigenschaften, aber es scheint nicht möglich zu sein, die Position alle n Minuten zu aktualisierenNSTimer
: Funktioniert, wenn die App im Vordergrund ausgeführt wird, scheint jedoch nicht für Hintergrundaufgaben ausgelegt zu sein- Lokale Benachrichtigungen: Lokale Benachrichtigungen können alle n Minuten geplant werden, es ist jedoch nicht möglich, Code auszuführen, um den aktuellen Standort abzurufen (ohne dass der Benutzer die App über die Benachrichtigung starten muss). Dieser Ansatz scheint auch kein sauberer Ansatz zu sein, da hierfür keine Benachrichtigungen verwendet werden sollten.
UIApplication:beginBackgroundTaskWithExpirationHandler
: Soweit ich weiß, sollte dies verwendet werden, um einige Arbeiten im Hintergrund (auch zeitlich begrenzt) zu beenden, wenn eine App in den Hintergrund verschoben wird, anstatt "lang laufende" Hintergrundprozesse zu implementieren.
Wie kann ich diese regelmäßigen Standortaktualisierungen im Hintergrund implementieren?
Antworten:
Ich habe mithilfe der Apple Developer Forums eine Lösung gefunden, um dies zu implementieren:
location background mode
NSTimer
im Hintergrund mitUIApplication:beginBackgroundTaskWithExpirationHandler:
n
ist kleiner alsUIApplication:backgroundTimeRemaining
es wird gut funktionieren. Wennn
es größer ist ,location manager
sollte das wieder aktiviert (und deaktiviert) werden, bevor keine Zeit mehr verbleibt, um zu verhindern, dass die Hintergrundaufgabe beendet wird.Dies funktioniert, da der Speicherort eine der drei zulässigen Arten der Hintergrundausführung ist .
Hinweis: Ich habe einige Zeit verloren, indem ich dies im Simulator getestet habe, wo es nicht funktioniert. Auf meinem Telefon funktioniert es jedoch einwandfrei.
quelle
Gehen Sie unter iOS 8/9/10 wie folgt vor, um die Hintergrundposition alle 5 Minuten zu aktualisieren:
Gehen Sie zu Projekt -> Funktionen -> Hintergrundmodi -> wählen Sie Standortaktualisierungen
Gehen Sie zu Projekt -> Info -> fügen Sie einen Schlüssel NSLocationAlwaysUsageDescription mit leerem Wert (oder optional einem beliebigen Text) hinzu.
Damit der Standort funktioniert, wenn sich Ihre App im Hintergrund befindet, und alle 5 Minuten Koordinaten an den Webdienst senden oder irgendetwas damit tun, implementieren Sie ihn wie im folgenden Code.
Ich verwende keine Hintergrundaufgaben oder Timer. Ich habe diesen Code mit meinem Gerät mit iOS 8.1 getestet, das einige Stunden auf meinem Schreibtisch lag, während meine App im Hintergrund ausgeführt wurde. Das Gerät war gesperrt und der Code lief die ganze Zeit ordnungsgemäß.
quelle
if ([self.locationManager respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)]) { [self.locationManager setAllowsBackgroundLocationUpdates:YES]; }
Ich habe dies in einer Anwendung getan, die ich entwickle. Die Timer funktionieren nicht, wenn sich die App im Hintergrund befindet, aber die App erhält ständig die Standortaktualisierungen. Ich habe irgendwo in der Dokumentation gelesen (ich kann es jetzt nicht finden, ich werde ein Update veröffentlichen, wenn ich es tue), dass eine Methode nur in einer aktiven Ausführungsschleife aufgerufen werden kann, wenn sich die App im Hintergrund befindet. Der App-Delegat verfügt auch im Hintergrund über eine aktive Ausführungsschleife, sodass Sie keine eigene erstellen müssen, damit dies funktioniert. [Ich bin nicht sicher, ob dies die richtige Erklärung ist, aber so habe ich verstanden, was ich gelesen habe]
Fügen Sie zunächst das
location
Objekt für den SchlüsselUIBackgroundModes
in die info.plist Ihrer App ein. Jetzt müssen Sie die Standortaktualisierungen an einer beliebigen Stelle in Ihrer App starten:Schreiben Sie als Nächstes eine Methode, um die Standortaktualisierungen beispielsweise
-(void)didUpdateToLocation:(CLLocation*)location
im App-Delegaten zu verarbeiten. Implementieren Sie dann die MethodelocationManager:didUpdateLocation:fromLocation
vonCLLocationManagerDelegate
in der Klasse, in der Sie den Standortmanager gestartet haben (da wir den Standortmanager-Delegaten auf 'self' gesetzt haben). Bei dieser Methode müssen Sie überprüfen, ob das Zeitintervall abgelaufen ist, nach dem Sie die Standortaktualisierungen durchführen müssen. Sie können dies tun, indem Sie jedes Mal die aktuelle Zeit speichern. Wenn diese Zeit abgelaufen ist, rufen Sie die Methode UpdateLocation von Ihrem App-Delegaten auf:Dadurch wird Ihre Methode alle 5 Minuten aufgerufen, auch wenn sich Ihre App im Hintergrund befindet. Wichtel: Diese Implementierung entlädt den Akku. Wenn die Genauigkeit Ihrer Standortdaten nicht kritisch ist, sollten Sie sie verwenden
[locationManager startMonitoringSignificantLocationChanges]
Bevor Sie dies zu Ihrer App hinzufügen, lesen Sie bitte das Location Awareness Programming Guide
quelle
Jetzt, da iOS6 der beste Weg ist, um für immer laufende Ortungsdienste zu haben, ist ...
Habe es einfach so getestet:
Ich startete die App, ging in den Hintergrund und bewegte mich einige Minuten im Auto. Dann gehe ich für 1 Stunde nach Hause und bewege mich wieder (ohne die App erneut zu öffnen). Die Standorte wurden erneut gestartet. Dann blieb er zwei Stunden stehen und fing wieder an. Alles wieder ok ...
VERGESSEN SIE NICHT, die neuen Ortungsdienste in iOS6 zu verwenden
quelle
Für jemanden, der einen Albtraum hat, ist das ein Problem. Ich habe eine einfache Lösung.
Fügen Sie den Timer hinzu, indem Sie Folgendes verwenden:
Vergessen Sie nicht, in info.plist "App-Register für Standortaktualisierungen" hinzuzufügen.
quelle
Folgendes benutze ich:
Ich starte das Tracking in AppDelegate folgendermaßen:
quelle
Leider scheinen alle Ihre Annahmen richtig zu sein, und ich glaube nicht, dass es einen Weg gibt, dies zu tun. Um die Akkulaufzeit zu verlängern, basieren die Ortungsdienste des iPhones auf Bewegung. Wenn sich das Telefon an einer Stelle befindet, ist es für Ortungsdienste unsichtbar.
Der
CLLocationManager
wird nur anrufenlocationManager:didUpdateToLocation:fromLocation:
wenn das Telefon eine Standortaktualisierung erhält. Dies geschieht nur, wenn einer der drei Standortdienste (Mobilfunkmast, GPS, WLAN) eine Änderung feststellt.Ein paar andere Dinge, die helfen könnten, weitere Lösungen zu finden:
Durch das Starten und Stoppen der Dienste wird die
didUpdateToLocation
Delegatenmethode aufgerufen, die jedochnewLocation
möglicherweise einen alten Zeitstempel hat.Regionsüberwachung könnte helfen
Beachten Sie beim Ausführen im Hintergrund, dass es möglicherweise schwierig ist, die von Apple genehmigte "vollständige" LocationServices-Unterstützung zu erhalten. Nach allem, was ich gesehen habe, haben sie speziell entworfen
startMonitoringSignificantLocationChanges
als stromsparende Alternative für Apps entwickelt, die Unterstützung für den Standort im Hintergrund benötigen, und ermutigen Entwickler nachdrücklich, diese zu verwenden, es sei denn, die App benötigt sie unbedingt.Viel Glück!
UPDATE: Diese Gedanken sind möglicherweise inzwischen veraltet. Es sieht so aus, als ob die Leute mit der Antwort von @wjans oben Erfolg haben.
quelle
startMonitoringSignificantLocationChanges
würde ich in diesem Fall kein Update geben.Ich habe eine App mit Ortungsdiensten geschrieben. Die App muss alle 10 Sekunden einen Ort senden. Und es hat sehr gut funktioniert.
Verwenden Sie einfach das Zeitlimit " allowDeferredLocationUpdatesUntilTraveled:" Methode Apples Dokument.
Was ich getan habe sind:
Erforderlich: Registrieren Sie den Hintergrundmodus für den Aktualisierungsort.
1. Erstellen Sie
LocationManger
undstartUpdatingLocation
mitaccuracy
undfilteredDistance
nach Belieben:2. Damit die App mit der
allowDeferredLocationUpdatesUntilTraveled:timeout
Methode im Hintergrund für immer ausgeführt wird, müssen SieupdatingLocation
mit einem neuen Parameter neu starten , wenn die App in den Hintergrund wechselt.3. App erhält aktualisierte Standorte wie gewohnt mit
locationManager:didUpdateLocations:
Rückruf:4. Sie sollten jedoch die Daten in
locationManager:didFinishDeferredUpdatesWithError:
Ihrem Rückruf für Ihren Zweck verarbeiten5. HINWEIS: Ich denke, wir sollten die Parameter
LocationManager
jedes Mal zurücksetzen, wenn die App zwischen Hintergrund- und Hintergrundmodus wechselt.quelle
pausesLocationUpdatesAutomatically = true
der Standortmanager angewiesen wird, Aktualisierungen anzuhalten, wenn anscheinend keine Standortänderung vorliegt ( Apples Dokument ). Jedenfalls habe ich den Falllocation manager pauses updates
noch nicht explizit getestet : D.pausesLocationUpdatesAutomatically = true
bewirkt, dass meine App den Standort nicht mehr aktualisiert.Dies wird für die Standortverfolgung im Hintergrund seit iOS 9 benötigt.
quelle
Ich habe die Methode von xs2bush verwendet, um ein Intervall zu erhalten (using
timeIntervalSinceDate
) und es ein wenig erweitert. Ich wollte sicherstellen, dass ich die erforderliche Genauigkeit erhalte, die ich benötige, und dass ich den Akku nicht entleere, indem ich das GPS-Radio mehr als nötig eingeschaltet lasse.Ich halte den Standort mit den folgenden Einstellungen kontinuierlich am Laufen:
Dies ist eine relativ geringe Belastung der Batterie. Wenn ich bereit bin, meine nächste regelmäßige Standortmessung durchzuführen, überprüfe ich zuerst, ob der Standort innerhalb meiner gewünschten Genauigkeit liegt. Wenn dies der Fall ist, verwende ich den Standort. Wenn nicht, dann erhöhe ich die Genauigkeit damit:
Ermitteln Sie meinen Standort, und sobald ich den Standort gefunden habe, drehe ich die Genauigkeit wieder zurück, um den Verbrauch der Batterie zu minimieren. Ich habe ein vollständiges Arbeitsbeispiel dafür geschrieben und auch die Quelle für den serverseitigen Code geschrieben, um die Standortdaten zu sammeln, in einer Datenbank zu speichern und Benutzern zu ermöglichen, GPS-Daten in Echtzeit anzuzeigen oder zuvor gespeicherte Routen abzurufen und anzuzeigen. Ich habe Clients für iOS, Android, Windows Phone und Java. Alle Clients sind nativ geschrieben und arbeiten im Hintergrund ordnungsgemäß. Das Projekt ist MIT-lizenziert.
Das iOS-Projekt ist für iOS 6 mit einem Basis-SDK von iOS 7 vorgesehen. Den Code erhalten Sie hier .
Bitte melden Sie ein Problem bei github an, wenn Sie Probleme damit sehen. Vielen Dank.
quelle
Es scheint, dass stopUpdatingLocation den Hintergrund-Watchdog-Timer auslöst. Deshalb habe ich ihn in didUpdateLocation durch Folgendes ersetzt:
Dies scheint das GPS effektiv auszuschalten. Der Selektor für den Hintergrund-NSTimer wird dann:
Ich schalte nur regelmäßig die Genauigkeit um, um alle paar Minuten eine hochgenaue Koordinate zu erhalten. Da der locationManager nicht gestoppt wurde, bleibt backgroundTimeRemaining auf seinem Maximalwert. Dies reduzierte den Batterieverbrauch von ~ 10% pro Stunde (mit konstanter kCLLocationAccuracyBest im Hintergrund) auf ~ 2% pro Stunde auf meinem Gerät
quelle
Es gibt einen Cocoapod APScheduledLocationManager , mit dem alle n Sekunden Hintergrund-Standortaktualisierungen mit der gewünschten Standortgenauigkeit abgerufen werden können .
Das Repository enthält auch eine in Swift 3 geschriebene Beispiel-App.
quelle
In iOS 9 und watchOS 2.0 gibt es eine neue Methode in CLLocationManager, mit der Sie den aktuellen Speicherort anfordern können: CLLocationManager: requestLocation (). Dies wird sofort abgeschlossen und gibt den Speicherort an den CLLocationManager-Delegaten zurück.
Mit dieser Methode können Sie jetzt jede Minute einen NSTimer verwenden, um einen Speicherort anzufordern, und müssen nicht mit den Methoden startUpdatingLocation und stopUpdatingLocation arbeiten.
Wenn Sie jedoch Standorte erfassen möchten, die auf einer Änderung von X Metern vom letzten Standort basieren, legen Sie einfach die Eigenschaft distanceFilter von CLLocationManger fest und rufen Sie X auf, um startUpdatingLocation () aufzurufen.
quelle
Im Anhang befindet sich eine Swift-Lösung, die auf Folgendem basiert:
Definieren Sie
App registers for location updates
in der info.plistLassen Sie den locationManager die ganze Zeit laufen
Wechseln Sie
kCLLocationAccuracy
zwischenBestForNavigation
(für 5 Sekunden, um den Standort zu ermitteln) undThreeKilometers
dem Rest der Wartezeit, um ein Entladen der Batterie zu vermeidenIn diesem Beispiel wird der Standort alle 1 Minute im Vordergrund und alle 15 Minuten im Hintergrund aktualisiert.
Das Beispiel funktioniert gut mit Xcode 6 Beta 6, das auf einem iOS 7-Gerät ausgeführt wird.
Im App-Delegaten (mapView ist ein optionaler Hinweis auf den mapView-Controller)
In der mapView (locationManager zeigt auf das Objekt im AppDelegate)
quelle