Ich schreibe eine Anwendung, die Aktualisierungen des Hintergrundstandorts mit hoher Genauigkeit und niedriger Frequenz erfordert . Die Lösung scheint eine NSTimer-Hintergrundaufgabe zu sein, die die Aktualisierungen des Standortmanagers startet und diese dann sofort herunterfährt. Diese Frage wurde schon einmal gestellt:
Wie erhalte ich in meiner iOS-Anwendung alle n Minuten ein Hintergrund-Standort-Update?
Abrufen des Benutzerstandorts alle n Minuten, nachdem die App in den Hintergrund geschaltet wurde
iOS Nicht das typische Problem mit dem Timer zur Verfolgung des Hintergrundstandorts
iOS-Hintergrundtimer mit langer Laufzeit und Hintergrundmodus "Standort"
iOS Vollzeit-Hintergrunddienst basierend auf Standortverfolgung
Aber ich habe noch kein Mindestbeispiel zum Laufen gebracht. Nachdem ich jede Permutation der oben akzeptierten Antworten ausprobiert hatte, stellte ich einen Ausgangspunkt zusammen. Hintergrund eingeben:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"ending background task");
[[UIApplication sharedApplication] endBackgroundTask:self.bgTask];
self.bgTask = UIBackgroundTaskInvalid;
}];
self.timer = [NSTimer scheduledTimerWithTimeInterval:60
target:self.locationManager
selector:@selector(startUpdatingLocation)
userInfo:nil
repeats:YES];
}
und die Delegatenmethode:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
NSLog(@"%@", newLocation);
NSLog(@"background time: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
[self.locationManager stopUpdatingLocation];
}
Das aktuelle Verhalten besteht darin, dass die backgroundTimeRemaining
Dekrementierung von 180 Sekunden auf Null (während der Protokollierung des Speicherorts) erfolgt und der Ablaufhandler dann ausgeführt wird und keine weiteren Standortaktualisierungen generiert werden. Wie ändere ich den obigen Code, um regelmäßig Standortaktualisierungen im Hintergrund auf unbestimmte Zeit zu erhalten ?
Update : Ich ziele auf iOS 7 ab und es scheint Hinweise darauf zu geben, dass sich Hintergrundaufgaben anders verhalten:
Starten Sie den Standort-Manager in iOS 7 über die Hintergrundaufgabe
Antworten:
Es scheint, dass dies
stopUpdatingLocation
den Hintergrund-Watchdog-Timer auslöst, also habe ich ihn ersetztdidUpdateLocation
durch:Dies scheint das GPS effektiv auszuschalten. Der Selektor für den Hintergrund wird
NSTimer
dann:Alles, was ich tue, ist, die Genauigkeit regelmäßig umzuschalten, um alle paar Minuten eine hochgenaue Koordinate zu erhalten. Da die Koordinate
locationManager
nicht gestoppt wurde,backgroundTimeRemaining
bleibt sie auf ihrem Maximalwert. Dies reduzierte den Batterieverbrauch von ~ 10% pro Stunde (mit KonstantekCLLocationAccuracyBest
im Hintergrund) auf ~ 2% pro Stunde auf meinem Gerät.quelle
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 die Methode " allowDeferredLocationUpdatesUntilTraveled: timeout " gemäß Apples Dokument.
Die Schritte sind wie folgt:
Erforderlich: Registrieren Sie den Hintergrundmodus für den Update-Speicherort.
1. Erstellen Sie LocationManger und startUpdatingLocation mit Genauigkeit und gefilterter Entfernung, wie Sie möchten:
2. Damit die App mit der Methode "allowDeferredLocationUpdatesUntilTraveled: timeout" im Hintergrund für immer ausgeführt wird, müssen Sie updatingLocation mit neuen Parametern neu starten, wenn die App in den Hintergrund wechselt.
3. App erhält aktualisierte Standorte wie gewohnt mit dem Rückruf "locationManager: didUpdateLocations:":
4. Sie sollten die Daten jedoch in dem Rückruf "locationManager: didFinishDeferredUpdatesWithError:" für Ihren Zweck verarbeiten
5. HINWEIS: Ich denke, wir sollten die Parameter von LocationManager jedes Mal zurücksetzen, wenn die App zwischen Hintergrund- und Hintergrundmodus wechselt.
quelle
allowsBackgroundLocationUpdates = YES
undrequestAlwaysAuthorization
oder Code hinzufügen müssenrequestWhenInUseAuthorization
. Beispiel: `CLLocationManager * locationManager = [[CLLocationManager alloc] init]; locationManager.delegate = self; locationManager.allowsBackgroundLocationUpdates = YES; [locationManager requestAlwaysAuthorization]; [locationManager startUpdatingLocation]; `Wenn Sie den Schlüssel
UIBackgroundModes
in Ihrer Listelocation
haben, müssen Sie keinebeginBackgroundTaskWithExpirationHandler
Methode verwenden. Das ist überflüssig. Sie verwenden es auch falsch (siehe hier ), aber das ist umstritten, da Ihre Plist eingestellt ist.Mit
UIBackgroundModes location
in der Liste wird die App nur so lange im Hintergrund ausgeführt, wie sie ausgeführtCLLocationManger
wird. Wenn SiestopUpdatingLocation
im Hintergrund anrufen, wird die App gestoppt und nicht erneut gestartet.Vielleicht könnten Sie
beginBackgroundTaskWithExpirationHandler
kurz vor dem Anruf anrufenstopUpdatingLocation
und dann nach demstartUpdatingLocation
Anruf den anrufenendBackgroundTask
, um den Hintergrund zu erhalten, während das GPS gestoppt ist, aber das habe ich nie versucht - es ist nur eine Idee.Eine andere Option (die ich nicht ausprobiert habe) besteht darin, den Standortmanager im Hintergrund laufen zu lassen. Wenn Sie jedoch einen genauen Standort erhalten, ändern Sie die
desiredAccuracy
Eigenschaft auf 1000 m oder höher, damit der GPS-Chip ausgeschaltet werden kann (um Batterie zu sparen). Wenn Sie dann 10 Minuten später eine weitere Standortaktualisierung benötigen, ändern Sie dendesiredAccuracy
Rücken auf 100 m, um das GPS einzuschalten, bis Sie einen genauen Standort erhalten. Wiederholen Sie diesen Vorgang.Wenn Sie
startUpdatingLocation
den Standortmanager anrufen , müssen Sie ihm Zeit geben, um eine Position zu bekommen. Sie sollten nicht sofort anrufenstopUpdatingLocation
. Wir lassen es maximal 10 Sekunden lang laufen oder bis wir einen nicht zwischengespeicherten Ort mit hoher Genauigkeit erhalten.Sie müssen zwischengespeicherte Speicherorte herausfiltern und die Genauigkeit des Speicherorts überprüfen, um sicherzustellen, dass er Ihrer erforderlichen Mindestgenauigkeit entspricht (siehe hier ). Das erste Update, das Sie erhalten, ist möglicherweise 10 Minuten oder 10 Tage alt. Die erste Genauigkeit, die Sie erhalten, kann 3000 m betragen.
Verwenden Sie stattdessen die APIs für signifikante Standortänderungen. Sobald Sie die Benachrichtigung über signifikante Änderungen erhalten haben, können Sie
CLLocationManager
einige Sekunden lang beginnen, um eine Position mit hoher Genauigkeit zu erhalten. Ich bin mir nicht sicher, ich habe die signifikanten Standortänderungsdienste nie genutzt.quelle
CoreLocation
Referenz scheint die VerwendungbeginBackgroundTaskWithExpirationHandler
bei der Verarbeitung von Standortdaten im Hintergrund zu empfehlen : "Wenn eine iOS-App mehr Zeit zum Verarbeiten der Standortdaten benötigt, kann sie mithilfe der Methode beginBackgroundTaskWithName: expirationHandler: der UIApplication-Klasse mehr Zeit für die Ausführung im Hintergrund anfordern." - developer.apple.com/library/ios/documentation/UserExperience/…locationManagerDidPauseLocationUpdates
. Ich habe dieses Verhalten 10 Mal überprüft!Wenn es Zeit ist, den Ortungsdienst zu starten und die Hintergrundaufgabe zu stoppen, sollte die Hintergrundaufgabe mit einer Verzögerung gestoppt werden (1 Sekunde sollte ausreichen). Andernfalls wird der Ortungsdienst nicht gestartet. Außerdem sollte der Ortungsdienst einige Sekunden (z. B. 3 Sekunden) eingeschaltet bleiben.
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
Wie wäre es mit einem Versuch mit
startMonitoringSignificantLocationChanges:
API? Es feuert definitiv mit weniger Frequenz und die Genauigkeit ist ziemlich gut. Darüber hinaus bietet es viel mehr Vorteile als die Verwendung andererlocationManager
APIs.Viel mehr zu dieser API wurde bereits unter diesem Link besprochen
quelle
This interface delivers new events only when it detects changes to the device’s associated cell towers
Sie müssen den Standortaktualisierungsmodus in Ihrer Anwendung hinzufügen, indem Sie den folgenden Schlüssel in Ihre info.plist einfügen.
didUpdateToLocation
Methode wird aufgerufen (auch wenn sich Ihre App im Hintergrund befindet). Anhand dieses Methodenaufrufs können Sie alles ausführenquelle
Nach iOS 8 gibt es einige Änderungen im CoreLocation Framework-bezogenen Hintergrundabruf und Aktualisierungen von Apple.
1) Apple führt die AlwaysAuthorization-Anforderung zum Abrufen des Standortupdates in der Anwendung ein.
2) Apple führt backgroundLocationupdates zum Abrufen des Standorts aus dem Hintergrund in iOS ein.
Um den Standort im Hintergrund abzurufen, müssen Sie die Standortaktualisierung in den Funktionen von Xcode aktivieren.
quelle
Um Standard-Standortdienste zu verwenden, während sich die Anwendung im Hintergrund befindet, müssen Sie zuerst die Hintergrundmodi auf der Registerkarte Funktionen der Zieleinstellungen aktivieren und Standortaktualisierungen auswählen.
Oder fügen Sie es direkt zur Info.plist hinzu .
Dann müssen Sie den CLLocationManager einrichten
Ziel c
Schnell
Ref: https://medium.com/@javedmultani16/location-service-in-the-background-ios-942c89cd99ba
quelle
quelle