Problème de géofences

InsouInsou Membre
juillet 2018 modifié dans API UIKit #1

Bonjour tout le monde,

J'ai un soucis assez étrange sur avec des geofences..

Je vous explique un peu mon application..
En gros, je reçois des "zones" de géofences et je les ajoute au téléphone.
La zone est un cercle avec un diamètre de plusieurs mètres/kilomètres.
Lorsque qu'un téléphone entre dans une zone (geofence), j'envoi une requête sur une page PHP.

Voila comment je m'y prend, si le login est bon, je récupère les zones, que j'ajoute au téléphone :

IncidentsViewController().stopAllMonitoring() // Supprime toute les régions monitorées
geotifications = [] // vide le tableau des geotifications
var items: [Data] = [] // Pour la sauvegarde locale
let TabZones = recupJSON["Data","Zones"].arrayValue
    for Zone in TabZones {
        if(Zone["Adresse"].stringValue.range(of:",") != nil){
            let TabCoordonnées = Zone["Adresse"].stringValue.components(separatedBy: ",")
            let latitude = TabCoordonnées[0]
            let longitude = TabCoordonnées[1]

            if((latitude.isNumberOrDouble == true) && (longitude.isNumberOrDouble == true)){
                let coordinate:CLLocationCoordinate2D = CLLocationCoordinate2DMake(Double(TabCoordonnées[0])!, Double(TabCoordonnées[1])!);
                let radius = Double(Zone["Rayon"].intValue)
                let identifier = NSUUID().uuidString
                let note = Zone["Note"].stringValue
                let id = Zone["Id"].intValue
                let date = Zone["Date"].stringValue
                let heure = Zone["Heure"].stringValue
                let notification = Zone["Notification"].stringValue

                // Geotification Entrante - DEBUT
                let clampedRadius = min(radius, locationManager.maximumRegionMonitoringDistance) // créer le rayon
                let nouvelleGeotification = Geotification(coordinate: coordinate, radius: clampedRadius, identifier: identifier+"-Entrant", note: note, id : id, date: date, heure: heure, notification: notification, eventType: .onEntry) // créer une nouvelle geotification
                IncidentsViewController().add(geotification: nouvelleGeotification, withMap: false) // On l'ajoute (pas sur la carte) dans la variable globale
                IncidentsViewController().startMonitoring(geotification: nouvelleGeotification) // On lance le geofencing

                // Sauvegarde locale
                let item = NSKeyedArchiver.archivedData(withRootObject: nouvelleGeotification)
                items.append(item)
                // Geotification Entrante - FIN

            }
            else{
                fonctions().WriteLogInFile(text: "La longitude ou latitude n'est pas bonne : "+longitude+"/"+latitude)
            }
        }
        else{
            fonctions().WriteLogInFile(text: "Mauvais format de zone : "+Zone["Adresse"].stringValue)
        }
    }

UserDefaults.standard.set(items, forKey: PreferencesKeys.savedItems)

Ensuite, pour la détection de zone, voici mon code :

extension AppDelegate: CLLocationManagerDelegate {

    // Zone entrante
    func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        if region is CLCircularRegion {
            updateHistoriqueIncident(type: "Entrant", region : region) // ma fonction pour envoyer la requête
            handleEvent(forRegion: region)
        }
    }
}

Ma fonction pour envoyer la requête :

func updateHistoriqueIncident(type : String, region : CLRegion){
    if let laGeotification = getGeotification(fromRegionIdentifier: region.identifier){ // On recupère la description
        let Config = ViewController().retourneConfigJson()
        let urlMessenger = Config["UrlMessenger"].stringValue
        let Token = Config["Token"].stringValue
        let Paramètres = [
            "Token": Token,
            "IdZone" : String(laGeotification.id),
            "Type" : type,
            "debug" : debugJSON
        ]

        if(!Token.isEmpty){
            _ = Alamofire.request(urlMessenger+"/"+api+"/incidents/updateZoneHistorique", method : .post, parameters: Paramètres)
        }
    }
    else{
        // JE PASSE ICI ALORS QUE JE NE DEVRAIS PAS :/
        let Config = ViewController().retourneConfigJson()
        let urlMessenger = Config["UrlMessenger"].stringValue
        let Token = Config["Token"].stringValue
        let Paramètres = [
            "Token": Token,
            "IdZone" : "ERREUR ZONE",
            "Type" : type,
            "debug" : debugJSON
        ]
        _ = Alamofire.request(urlMessenger+"/"+api+"/incidents/TestZoneHistoriquePourLeBug", method : .post, parameters: Paramètres)
    }
}

La fonction getGeotification :

func getGeotification(fromRegionIdentifier identifier: String) -> Geotification? {
    let savedItems = UserDefaults.standard.array(forKey: PreferencesKeys.savedItems) as? [NSData]
    let geotifications = savedItems?.map { NSKeyedUnarchiver.unarchiveObject(with: $0 as Data) as? Geotification }
    let index = geotifications?.index { $0?.identifier == identifier }
    return index != nil ? geotifications?[index!] : nil
}

Le soucis est que lorsque je fais mes tests en local en modifiant la position du GPS via Xcode, j'ai jamais de soucis, tout fonctionne bien et une fois en condition réelle, j'ai l'impression que ça fonctionne au début et qu'ensuite (le jour d'après ?), le téléphone ne trouve plus les geotifications.
Comme si elles disparaissaient au bout d'un certain temps ? C'est possible que le téléphone "purge" ses géofences tout seul au bout d'un certains temps ? Est-ce-qu'il faut leur donner une date d'expiration ? (je crois que c'est comme ça sur Android)

Bref, je suis un peu dans le flou, si quelqu'un a des pistes, c'est pas de refus parce que là, je coince :/

Merci de votre aide ^^

Mots clés:

Réponses

  • CéroceCéroce Membre, Modérateur
    juillet 2018 modifié #2

    J'ai pas mal travaillé sur le sujet, et je peux te dire que sur un device, on est très loin de recevoir les CLRegions dès qu'on entre dedans. Parfois, il faut attendre deux jours! Et il faut que l'utilisateur y reste un certain temps (~15 mn).
    Bref, c'est casse-pieds à tester.

    Vérifie également les autorisations de géoloc, l'appli doit être en "Always" pour détecter les régions en tâche de fond.

    P.S.: ton code est dégueu.

  • InsouInsou Membre
    juillet 2018 modifié #3

    Du coup, on ne peut pas être averti de manière fiable quand on rentre dans une zone ?
    Là j'ai l'impression que la geofence à disparu.. ce qui me semble assez surprenant :/
    Hier j'ai fais un test réel, ça c'est bien passé.. je vais voir ce soir quand je re-rentrerai dans la zone si elle est détectée ou pas.

    L'application a bien en "Always" dans ses permissions.

    PS: Je sais.

Connectez-vous ou Inscrivez-vous pour répondre.