Wie kann ich den Benutzer auffordern, Ortungsdienste zu aktivieren, nachdem der Benutzer seine Verwendung verweigert hat?

75

Ich habe eine Anwendung mit einer expliziten Benutzerinteraktion, die den aktuellen Standort des Benutzers verwendet. Wenn der Benutzer den Zugriff auf Ortungsdienste verweigert, möchte ich nachfolgende Verwendungen, um den Benutzer aufzufordern, zu den Einstellungen zu wechseln und die Ortungsdienste für meine App wieder zu aktivieren.

Ich möchte das Verhalten der integrierten Maps-App:

  1. Standortwarnungen unter Einstellungen> Allgemein> Zurücksetzen> Standortwarnungen zurücksetzen zurücksetzen.
  2. Starten Sie die Karten-App.
  3. Tippen Sie unten links auf die Schaltfläche Aktueller Standort.
  4. Eingabeaufforderungen für Karten mit "" Karten "möchten Ihren aktuellen Standort verwenden" | "Nicht zulassen" | "Ermöglichen".
  5. Wählen Sie die Option "Nicht zulassen".
  6. Tippen Sie erneut auf die Schaltfläche Aktueller Standort in der unteren linken Ecke.
  7. Karten werden mit der Option "Standortdienste aktivieren" aktiviert, damit "Karten" Ihren Standort bestimmen können "| "Einstellungen" | "Stornieren".

In meiner eigenen App führt der gleiche grundlegende Ablauf dazu, dass meine CLLocationManagerDelegate -locationManager: didFailWithError: -Methode im letzten Schritt mit einem kCLErrorDenied-Fehler aufgerufen wird und der Benutzer nicht die Option erhält, die Einstellungen-App zu öffnen, um sie zu korrigieren.

Ich könnte meine eigene Warnung als Reaktion auf den Fehler anzeigen, aber es wäre nicht möglich, die Einstellungen-App wie die Warnung zu starten, die das Betriebssystem bereitstellen kann, wie sie von der integrierten Karten-App verwendet wird.

Gibt es etwas in der CLLocationManager-Klasse, das mir fehlt, das mir dieses Verhalten geben könnte?

GBegen
quelle
Im Moment zeige ich dem Benutzer nur eine Warnung an und fordere ihn auf, zu Einstellungen zu gehen, um sie wieder zu aktivieren. Ich würde auch gerne eine bessere Lösung hören.
Donkim
Ich hätte auch gerne eine Antwort darauf, sicherlich gibt es einen besseren Weg
conorgriffin
Ich fand, dass CoreLocation aus diesem Grund nicht zufriedenstellend war. Am Ende habe ich die Skyhook-Bibliothek verwendet, die einfach zu integrieren und gut dokumentiert ist. Die Koordinaten scheinen auch genauer zu sein. Der einzige Nachteil besteht darin, dass eine 1,5-MB-Dylib mit der Anwendung gebündelt werden muss.
Chris Mowforth
Ich denke, viele der Antworten zeigen Antworten für stackoverflow.com/questions/5655674/…
Pramod More

Antworten:

42

Mit iOS8 können Sie den Benutzer endlich über openURL mit der Einstellungen-App verknüpfen. Sie können beispielsweise eine UIAlertView mit einer einzigen Schaltfläche erstellen, die den Benutzer zur Einstellungen-App führt:

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:ICLocalizedString(@"LocationServicesPermissionTitle")
                                                    message:ICLocalizedString(@"LocationPermissionGeoFenceMessage")
                                                   delegate:self
                                          cancelButtonTitle:@"Settings"
                                          otherButtonTitles:nil];
    [alert show];

In Ihrem UIAlertView-Delegaten:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    [alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
    [[UIApplication sharedApplication] openURL: [NSURL URLWithString: UIApplicationOpenSettingsURLString]];
}
mobileideafactory.com
quelle
4
Dies ist viel besser als in iOS 7 und früher, aber immer noch nicht perfekt, da die URL Sie zu einem Bildschirm führt, der eine Ebene höher liegt und auf dem der Benutzer die Einstellung tatsächlich ändern kann.
GBegen
Zumindest ab iOS 10 gelangen Sie direkt zu den App-Einstellungen, in denen auch der Standort aufgeführt ist.
Seeküste von Tibet
32

Aktualisieren:

Ab iOS 8 gibt es jetzt die Konstante, UIApplicationOpenSettingsURLStringdie eine URL darstellt, die beim Öffnen die App "Einstellungen" mit den Einstellungen Ihrer Anwendung öffnet (wo der Benutzer die Standortdienste wieder aktivieren kann).


Original:

Es gibt keine Möglichkeit für Sie, dies zu tun. Ihre einzige echte Option besteht darin, eine Warnung anzuzeigen, die den Benutzer darüber informiert, dass für Ihre Anwendung Ortungsdienste erforderlich sind, und ihn anzuweisen, manuell zur App Einstellungen zu wechseln und sie zu aktivieren.

Lily Ballard
quelle
Ich habe die Apple-Dokumente gelesen und unten eine Antwort basierend auf den Dokumenten veröffentlicht, aber ich habe sie nicht selbst getestet. Ist dies eine Änderung in den SDKs oder waren sie gleich?
Nur ein Codierer
Ich fürchte, diese Antwort ist nicht mehr richtig. Möglicherweise möchten Sie Ihre Antwort aktualisieren oder löschen.
James Webster
Hier ist ein großartiges Beispiel in Swift nshipster.com/core-location-in-ios-8 , das ich sehr hilfreich fand. Es wird gezeigt, wie Sie eine Warnung erstellen, die zur SettingsVerwendung umleitet UIApplicationOpenSettingsURLString.
dmk12
17

AlertViews sind in iOS 8 veraltet . Es gibt jetzt eine bessere Möglichkeit, Warnungen mit dem neuen AlertController zu verarbeiten:

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString( @"Enter your title here", @"" ) message:NSLocalizedString( @"Enter your message here.", @"" ) preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Cancel", @"" ) style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:NSLocalizedString( @"Settings", @"" ) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
   [[UIApplication sharedApplication] openURL:[NSURL URLWithString:
                                                    UIApplicationOpenSettingsURLString]];
}];

[alertController addAction:cancelAction];
[alertController addAction:settingsAction];

[self presentViewController:alertController animated:YES completion:nil];
Markus
quelle
7

Laut Apples Docs zur locationServicesEnabled- Methode.

Der Benutzer kann Standortdienste in der Anwendung "Einstellungen" aktivieren oder deaktivieren, indem er den Schalter "Standortdienste" unter "Allgemein" umschaltet.

Sie sollten den Rückgabewert dieser Methode überprüfen, bevor Sie mit Standortaktualisierungen beginnen, um festzustellen, ob für den Benutzer Standortdienste für das aktuelle Gerät aktiviert sind. Wenn diese Methode NO zurückgibt und Sie trotzdem Standortaktualisierungen starten, fordert das Core Location Framework den Benutzer auf, zu bestätigen, ob die Standortdienste wieder aktiviert werden sollen.

Können Sie also nicht einfach die Aktualisierung der Ortungsdienste starten, um eine Warnung auszulösen?

Nur ein Kodierer
quelle
15
Dies funktioniert nicht wirklich und hat wahrscheinlich mit der subtilen Unterscheidung zwischen locationServicesEnabled und Authorized zu tun . Wenn sie deaktiviert sind, werden Sie zur Aktivierung aufgefordert. Wenn sie jedoch aktiviert, aber abgelehnt werden, wird nichts unternommen. Dies ist jedoch eine sehr verwirrende Dokumentation.
SG1
locationServicesEnabled ist eine veraltete Methode.
Ben Patch
6

Hier ist die schnelle 3-Implementierung des von Markus und bjc bereitgestellten Codes.

let alertController = UIAlertController(title: NSLocalizedString("Enter your title here", comment: ""), message: NSLocalizedString("Enter your message here.", comment: ""), preferredStyle: .alert)

let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .default) { (UIAlertAction) in
                UIApplication.shared.openURL(NSURL(string: UIApplicationOpenSettingsURLString)! as URL)
            }

alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
            self.present(alertController, animated: true, completion: nil)
Munib
quelle
5

In Swift 4 gibt es ein Update in der Syntax.

Swift 4

extension UIAlertController {

    func createSettingsAlertController(title: String, message: String) {

      let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)

      let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
      let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .default) { (UIAlertAction) in
        UIApplication.shared.open(URL(string: UIApplicationOpenSettingsURLString)! as URL, options: [:], completionHandler: nil)
      }

      alertController.addAction(cancelAction)
      alertController.addAction(settingsAction)
      self.present(alertController, animated: true, completion: nil)

   }
}
omi23
quelle
2

Ich denke, Sie werden eine Antwort auf Ihre Frage haben, wenn Apple über ein neues SDK nachdenkt. Zum gegenwärtigen Zeitpunkt und soweit ich weiß, ist dies nicht möglich:

Kein URL-Handler verfügbar
Keine verwendbare Methode zum Aufrufen

Aber ... Wie Maps es tut, kann dies getan werden, aber wahrscheinlich unter Verwendung einer privaten API. Wenn Sie mit dieser Art der Codierung keine Angst haben, sollten Sie dort meiner Meinung nach suchen.

Oliver
quelle
1

Hier ist eine Swift-Version des Codes in der Antwort von Markus. Dieser Code erstellt eine Warnung, die dem Benutzer die Möglichkeit gibt, Einstellungen zu öffnen.

let alertController = UIAlertController(title: NSLocalizedString("Enter your title here", comment: ""), message: NSLocalizedString("Enter your message here.", comment: ""), preferredStyle: .Alert)

let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .Cancel, handler: nil)
let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .Default) { (UIAlertAction) in
    UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
}

alertController.addAction(cancelAction)
alertController.addAction(settingsAction)
self.presentViewController(alertController, animated: true, completion: nil)
bjc
quelle
1

Schnell ,

Sobald Sie die Standortdienste für eine App deaktivieren, werden bei den Delegierungsmethoden des Standortmanagers Fehler angezeigt. Wenn wir also einen Fehler erhalten, können wir überprüfen, ob die Ortungsdienste aktiviert / deaktiviert sind. Entsprechend dem Ergebnis können wir den Benutzer bitten, zu den Einstellungen zu gehen und die Ortungsdienste zu aktivieren.

Fügen Sie in der Delegierungsmethode Ihres Standortmanagers für Fehler eine Standortberechtigungsprüfung hinzu

func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
            //check  location permissions
            self.checkLocationPermission()
        }
}

Code zur Überprüfung der Standortberechtigung

//check location services enabled or not

    func checkLocationPermission() {
        if CLLocationManager.locationServicesEnabled() {
            switch(CLLocationManager.authorizationStatus()) {
            case .notDetermined, .restricted, .denied:
                //open setting app when location services are disabled
            openSettingApp(message:NSLocalizedString("please.enable.location.services.to.continue.using.the.app", comment: ""))
            case .authorizedAlways, .authorizedWhenInUse:
                print("Access")
            }
        } else {
            print("Location services are not enabled")
            openSettingApp(message:NSLocalizedString("please.enable.location.services.to.continue.using.the.app", comment: ""))
        }
    }

Code zum Öffnen der Einstellungs-App,

//open location settings for app
func openSettingApp(message: String) {
    let alertController = UIAlertController (title: APP_NAME_TITLE, message:message , preferredStyle: .alert)

    let settingsAction = UIAlertAction(title: NSLocalizedString("settings", comment: ""), style: .default) { (_) -> Void in
        guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
            return
        }

        if UIApplication.shared.canOpenURL(settingsUrl) {
            UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
        }
    }
    alertController.addAction(settingsAction)
    let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .default, handler: nil)
    alertController.addAction(cancelAction)

    present(alertController, animated: true, completion: nil)
}
Pramod Mehr
quelle
1

neueste schnelle Version basierend auf den obigen Antworten.

func showSettingsAlert(_ from:UIViewController, title:String?, message:String?) {

        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)

        let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)

        let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment: ""), style: .default) { (UIAlertAction) in

            guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else {
                return
            }

            if UIApplication.shared.canOpenURL(settingsUrl) {
                UIApplication.shared.open(settingsUrl, options: [:], completionHandler: nil)
            }
        }

        alertController.addAction(cancelAction)
        alertController.addAction(settingsAction)
        from.present(alertController, animated: true, completion: nil)
    }
Chris
quelle
0

Swift 3-Erweiterung zum Erstellen von Einstellungen Alarm Controller:

Foundation importieren

extension UIAlertController {
    func createSettingsAlertController(title: String, message: String) -> UIAlertController {
        let controller = UIAlertController(title: title, message: message, preferredStyle: .alert)

        let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment:"" ), style: .cancel, handler: nil)
        let settingsAction = UIAlertAction(title: NSLocalizedString("Settings", comment:"" ), style: .default, handler: { action in
            UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
        })
        controller.addAction(cancelAction)
        controller.addAction(settingsAction)

        return controller
    }
}
Roman Barzyczak
quelle