Problème de géofences
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 ^^
Réponses
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.
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.