web-dev-qa-db-fra.com

Comment puis-je inviter l'utilisateur à activer les services de localisation après que l'utilisateur en a refusé l'utilisation?

J'ai une application avec une interaction utilisateur explicite qui utilise l'emplacement actuel de l'utilisateur. Si l'utilisateur refuse l'accès aux services de localisation, je souhaite néanmoins des utilisations ultérieures pour l'inviter à accéder aux paramètres et à réactiver les services de localisation pour mon application.

Le comportement que je souhaite est celui de l'application Maps intégrée:

  1. Réinitialisez les avertissements d'emplacement dans Paramètres> Général> Réinitialiser> Réinitialiser les avertissements d'emplacement.
  2. Démarrez l'application Maps.
  3. Appuyez sur le bouton Emplacement actuel dans le coin inférieur gauche.
  4. Maps affiche "" Maps "voudrait utiliser votre position actuelle" | "Ne pas autoriser" | "Permettre".
  5. Choisissez l'option "Ne pas autoriser".
  6. Appuyez à nouveau sur le bouton Emplacement actuel dans le coin inférieur gauche.
  7. Maps affiche "Activer les services de localisation pour permettre à" Cartes "de déterminer votre position" | "Paramètres" | "Annuler".

Dans ma propre application, le même flux de base entraîne ma méthode CLLocationManagerDelegate -locationManager: didFailWithError: appelée avec une erreur kCLErrorDenied à l'étape finale et l'utilisateur n'a pas la possibilité d'ouvrir l'application Paramètres pour la corriger.

Je pouvais afficher ma propre alerte en réponse à l'erreur, mais je n'aurais pas la possibilité de lancer l'application Paramètres, contrairement à l'alerte que le système d'exploitation peut fournir telle qu'elle est utilisée par l'application Cartes intégrée.

Y a-t-il quelque chose dans la classe CLLocationManager qui me manque qui pourrait me donner ce comportement?

69
GBegen

Avec iOS8, vous pouvez enfin lier l'utilisateur à l'application Réglages via openURL. Par exemple, vous pouvez créer un UIAlertView avec un seul bouton qui conduit l'utilisateur à l'application Paramètres:

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

Dans votre délégué UIAlertView:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    [alertView dismissWithClickedButtonIndex:buttonIndex animated:YES];
    [[UIApplication sharedApplication] openURL: [NSURL URLWithString: UIApplicationOpenSettingsURLString]];
}
42

Mettre à jour:

Depuis iOS 8, il existe maintenant la constante UIApplicationOpenSettingsURLString qui représente une URL qui, lorsqu'elle est ouverte, ouvre l'application Paramètres aux paramètres de votre application (où l'utilisateur peut ensuite réactiver les services de localisation).


Original:

Il n'y a aucun moyen pour vous de faire cela. Votre seule option consiste à afficher une alerte informant l'utilisateur que votre application nécessite des services de localisation et leur demandant d'aller manuellement à l'application Paramètres et de l'activer.

32
Lily Ballard

AlertViews est obsolète dans iOS 8. Il existe désormais un meilleur moyen de gérer les alertes à l'aide du nouveau AlertController:

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];
16
Markus

Selon Documents d'Apple sur la méthode locationServicesEnabled.

L'utilisateur peut activer ou désactiver les services de localisation à partir de l'application Paramètres en basculant le commutateur Services de localisation en Général.

Vous devez vérifier la valeur de retour de cette méthode avant de commencer les mises à jour d'emplacement pour déterminer si les services de localisation de l'utilisateur sont activés pour le périphérique actuel. Si cette méthode renvoie NO et que vous démarrez quand même les mises à jour d'emplacement, l'infrastructure Core Location invite l'utilisateur à confirmer si les services de localisation doivent être réactivés.

Vous ne pouvez donc pas démarrer les mises à jour des services de localisation de quelque manière que ce soit pour que l'alerte soit invitée?

Voici l'implémentation Swift 3 du code fourni par Markus et bjc.

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)
5
Munib

Dans Swift 4, il existe une mise à jour de sa syntaxe.

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)

   }
}
3
omi23

Je suppose que vous aurez une réponse à votre question lorsque Apple réfléchira à un nouveau SDK. À l'heure actuelle et pour autant que je sache, ce n'est pas possible:

Aucun gestionnaire d'URL disponible
Aucune méthode utilisable pour appeler 

Mais ... Comme le fait Google Maps, cela peut être fait, mais probablement à l'aide d'une API privée. Si vous n’avez pas peur de ce type de codage, vous devriez chercher là, à mon avis.

2
Oliver

Rapide ,

Une fois que vous avez désactivé les services de localisation pour une application, les méthodes de délégation d'emplacement manager commencent à afficher une erreur. Ainsi, en cas d'erreur, nous pouvons vérifier si les services de localisation sont activés/désactivés. Et en fonction du résultat, nous pouvons demander à l'utilisateur d'accéder aux paramètres et d'activer les services de localisation. 

Dans la méthode de délégation de votre responsable d'emplacement pour erreur, ajoutez une vérification d'autorisation d'emplacement.

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

Code pour la vérification d'autorisation de localisation

//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 pour ouvrir les paramètres de l'application,

//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)
}
1
Pramod More

Voici une version Swift du code dans la réponse de Markus. Ce code crée une alerte qui donne à l'utilisateur la possibilité d'ouvrir les paramètres.

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)
1
bjc

dernière version de Swift basée sur les réponses ci-dessus.

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)
    }
0
Chris

Extension Swift 3 pour la création d'un contrôleur d'alerte de paramètres:

fondation d'importation

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
    }
}
0
Roman Barzyczak