Frage Wird iOS die beendete App aktivieren, wenn sie mit dem Speicherort für UIBackgroundModes registriert ist?


Ich weiß, dass iOS, wenn eine App "Standortdienst mit signifikanter Änderung" verwendet, von iOS aktiviert wird, wenn eine Standortaktualisierung geliefert wird, auch wenn die App beendet wird.

Ich konnte keine klare Antwort auf den Fall finden, wenn die App Standard-Ortungsdienste verwendet und den Ort als Schlüssel für UIBackgroundModes festlegt: Wird iOS es auch aktivieren, um das Update zu liefern, selbst wenn es beendet wird? Oder muss die App im Hintergrund ausgeführt werden, um den Standortaktualisierungsrückruf zu erhalten?

AKTUALISIEREN: Zu der Zeit, als ich das fragte, hatte ich nicht die Zeit, es zu testen. Aber nachdem ich hier eine Antwort erhalten habe, habe ich diesen Code in den Delegaten meiner Anwendung geschrieben, um zu sehen, ob meine beendete App bei einem Standort-Update erneut gestartet wird. Ich zeige eine UILocalNotification an, wenn ich über das Update informiert werde. Als ich jedoch meine App beendete und dann meinen Standort in der Stadt änderte, wurde die App nicht neu gestartet und ich erhielt keine Updates. Kannst du mir sagen, was ich falsch mache?

UPDATE # 2: Nach den endgültigen Ergebnissen in diesem Q & A ist nichts falsch mit diesem Code und es ist das erwartete Verhalten für eine App, die Standard-Standortdienste verwendet, nicht nach der Beendigung neu gestartet werden.

Ich habe den Speicherort als einen der UIBackgroundModes in der Info.plist-Datei hinzugefügt.

Und das sind die standortbezogenen Teile meines App-Delegaten:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    [UIApplication sharedApplication].applicationIconBadgeNumber = 0;

    m_locManager = [[CLLocationManager alloc] init];
    m_locManager.delegate = self;
    [m_locManager startUpdatingLocation];
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [m_locManager startUpdatingLocation];
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog("%@", [NSString stringWithFormat:@"Background Fail %@", [error localizedDescription]]);
}

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
    UILocalNotification * theNotification = [[UILocalNotification alloc] init];
    theNotification.alertBody = [NSString stringWithFormat:@"Background location %.06f %.06f %@" , newLocation.coordinate.latitude, newLocation.coordinate.longitude, newLocation.timestamp];
    theNotification.alertAction = @"Ok";

    theNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];

    [[UIApplication sharedApplication] scheduleLocalNotification:theNotification];
}

23
2017-09-02 21:42


Ursprung


Antworten:


Ja, es wird sich genauso verhalten, außer dass es öfter Updates erhält (und somit mehr Batterie verbraucht).

Quelle: App States und Multitasking unter dem Abschnitt Verfolgen des Benutzerstandorts.

BEARBEITEN Nach dem erneuten Lesen scheint es, dass das Programm von einem wacht wird suspendiert Staat aber nicht a beendet ein. Ich glaube nicht, dass Sie diesen Hintergrundmodus wirklich brauchen. Es wurde für Apps entwickelt, die genaue Ortsinformationen benötigen (z. B. Turn-by-Turn-Navigation). Sehen Sie sich den Abschnitt im Programm zur Standortprogrammierung zur "regionsbasierten" Programmierung an. Das Beispiel in Ihren Kommentaren wird als eine der Anwendungen dieser App aufgeführt.

BEARBEITEN WIEDER Laut der Diskussion in den Kommentaren scheint die endgültige Lösung eine signifikante Standortänderung zu setzen, bis der Benutzer nahe genug ist, und dann auf die Feinstandortänderung umzuschalten (und hofft, dass die App während dieser Zeit nicht beendet wird ^^)


4
2017-09-03 01:26



Sieht so aus, als ob Sie eine praktikable Lösung gefunden haben und es scheint, als würde die Verwendung des signifikanten Änderungsrahmens Ihnen ein wenig Akkulaufzeit sparen, solange es für Ihre Zwecke genau genug ist. Ihre Lösung ist auch von Vorteil, da Sie potenziell mehr als das Limit von 20 Regionen gleichzeitig überwachen können, indem Sie nur die Regionen überwachen, denen Sie am nächsten sind.

Ich brauche eine ähnliche Funktionalität, denke aber nicht, dass die signifikante Änderung für meine App genau genug wäre, also habe ich etwas mehr gegraben und folgendes gefunden.

Pro Location Awareness Programmierhandbuch, unter "Überwachung formbasierter Regionen":

In iOS werden Regionen, die mit Ihrer App verknüpft sind, jederzeit verfolgt, auch wenn Ihre App nicht ausgeführt wird. Wenn eine Bereichsgrenze überschritten wird, während eine App nicht ausgeführt wird, wird diese App erneut in den Hintergrund verschoben, um das Ereignis zu verarbeiten. Wenn die App beim Eintreten des Ereignisses ausgesetzt wird, wird sie ebenfalls aufgeweckt und erhält eine kurze Zeit, um das Ereignis zu verarbeiten.

Und auch in "Umgang mit Grenzüberschreitungen für eine Region":

Jedes Mal, wenn der aktuelle Standort des Benutzers einen Grenzbereich überquert, generiert das System ein entsprechendes Regionsereignis für Ihre App. Wenn Ihre App bereits ausgeführt wird, werden diese Ereignisse direkt an die Stellvertreter aller aktuellen Standortmanagerobjekte gesendet. Wenn Ihre App nicht ausgeführt wird, startet das System sie im Hintergrund, sodass sie reagieren kann. Apps können die folgenden Methoden implementieren, um Grenzüberschreitungen zu behandeln:

locationManager: didEnterRegion:

locationManager: didExitRegion:

In meinem Fall musste ich nur eine Benachrichtigung auslösen, wenn die Grenze überschritten wurde. Daher setzte ich mein AppDelegate auf CLLocationManagerDelegate, erstellte eine locationManager-Eigenschaft und fügte dies in meine Implementierungsdatei ein:

- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.locationManager.delegate = self;
    return YES;
}

- (CLLocationManager *)locationManager
{
    if (!_locationManager) {
        _locationManager = [[CLLocationManager alloc] init];
        _locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
    }
    return _locationManager;
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
    UILocalNotification *notification = [[UILocalNotification alloc] init];
    notification.alertBody = NSLocalizedString(@"You crossed a boundary!", @"user crossed a boundary");
    [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}

Tests zeigen, dass dies funktioniert, ohne dass der UIBackgroundModes-Standortschlüssel festgelegt werden muss. In diesem Anwendungsfall behandelt das Betriebssystem die Grenzüberwachung für Sie und sendet das Ereignis dann lange genug an Ihre App, um das Ereignis zu verarbeiten. Das tut es nicht starten Die App wird nur für einige Sekunden im Hintergrund ausgeführt, um das Grenzereignis zu verarbeiten. Während dieser Zeit können Sie nur relevante Aktivitäten ausführen. Hoffe das hilft auch jemand anderem!


3
2018-05-03 15:30



Sobald Sie die App beenden, werden die Standortaktualisierungen an die Anwendung gesendet

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

Sie müssen die Standortaktualisierungen innerhalb dieser Delegatmethode sammeln, indem Sie wie folgt nach dem Startschlüssel suchen:

if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey])
{
//Code to handle the location update
}

Hoffe, das ist was du suchst. Ja, Sie müssen den Schlüssel "Required backround modes" mit dem Wert "App registers for location updates" in plist einstellen.


2
2017-08-30 15:59