J'ai du mal à faire fonctionner cela lorsque l'application n'est pas en cours d'exécution. J'ai locationManager:didRangeBeacons:inRegion:
implémenté et il est appelé lorsque l'application s'exécute au premier plan ou en arrière-plan, mais il ne semble rien faire lorsque je quitte l'application et verrouille l'écran. L'icône des services de localisation disparaît et je ne sais jamais que je suis entré dans une plage de balises. La notification locale doit-elle toujours fonctionner?
J'ai des mises à jour de localisation et utilise des accessoires Bluetooth LE sélectionnés dans les modes d'arrière-plan (XCode 5), je ne pensais pas en avoir besoin.
Toute aide grandement appréciée.
-(void)watchForEvents { // this is called from application:didFinishLaunchingWithOptions
id class = NSClassFromString(@"CLBeaconRegion");
if (!class) {
return;
}
CLBeaconRegion * rflBeacon = [[CLBeaconRegion alloc] initWithProximityUUID:kBeaconUUID identifier:kBeaconString];
rflBeacon.notifyOnEntry = YES;
rflBeacon.notifyOnExit = NO;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager startRangingBeaconsInRegion:rflBeacon];
[self.locationManager startMonitoringForRegion:rflBeacon];
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
if (beacons.count == 0 || eventRanged) { // breakpoint set here for testing
return;
}
eventRanged = YES;
if (backgroundMode) { // this is set in the EnterBackground/Foreground delegate calls
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = [NSString stringWithFormat:@"Welcome to the %@ event.",region.identifier];
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
// normal processing here...
}
La surveillance peut lancer une application qui n'est pas en cours d'exécution. La distance ne peut pas.
La clé de la surveillance du lancement de votre application consiste à définir cet indicateur mal documenté sur votre Cela peut lancer votre application sur une transition de région même après avoir redémarré complètement votre téléphone. Mais il y a quelques mises en garde:CLBeaconRegion
: region.notifyEntryStateOnDisplay = YES;
NSLog
à applicationDidEnterBackground
et à d'autres méthodes dans votre AppDelegate pour voir ce qui se passe.)CLBeaconRegion
. Je l'ai vu prendre jusqu'à quatre minutes.En ce qui concerne la télémétrie, même si la télémétrie ne peut pas réveiller votre application, vous pouvez faire en sorte que votre application effectue à la fois la surveillance et la télémétrie. Si la surveillance réveille votre application et la met en arrière-plan pendant quelques secondes, les rappels de gamme démarrent immédiatement. Cela vous donne la possibilité d'effectuer des actions de télémétrie rapide pendant que votre application est toujours en cours d'exécution.
EDIT: Une enquête plus approfondie prouve que notifyEntryStateOnDisplay
n'a aucun effet sur la surveillance en arrière-plan, donc ce qui précède devrait fonctionner, que vous ayez ou non cet indicateur. Voir cette explication détaillée et discussion des retards que vous pouvez rencontrer
Code pour iOS 9 pour répartir les balises en arrière-plan, en utilisant Mises à jour de l'emplacement :
Ouvrez Paramètres du projet -> Capacités -> Modes d'arrière-plan -> Basculez Location Updates
Et Uses Bluetooth LE accessories
Sur ON
.
Créez un CLLocationManager
, demandez Always
une autorisation de surveillance (n'oubliez pas d'ajouter le Application does not run in background
À NO
et NSLocationAlwaysUsageDescription
dans l'application de info.plist
) Et définissez les propriétés suivantes:
locationManager!.delegate = self
locationManager!.pausesLocationUpdatesAutomatically = false
locationManager!.allowsBackgroundLocationUpdates = true
Commencer la télémétrie pour les balises et la région de surveillance:
locationManager!.startMonitoringForRegion(yourBeaconRegion)
locationManager!.startRangingBeaconsInRegion(yourBeaconRegion)
locationManager!.startUpdatingLocation()
// Optionally for notifications
UIApplication.sharedApplication().registerUserNotificationSettings(
UIUserNotificationSettings(forTypes: .Alert, categories: nil))
Implémentez le CLLocationManagerDelegate
et dans votre didEnterRegion
envoyez les messages startRangingBeaconsInRegion()
et startUpdatingLocation()
(envoyez également la notification en option) et définissez le stopRangingBeaconsInRegion()
et stopUpdatingLocation()
dans didExitRegion
Soyez conscient que cette solution fonctionne mais qu'elle n'est pas recommandée par Apple en raison de la consommation de la batterie et de la confidentialité des clients!
Voici le processus que vous devez suivre pour varier en arrière-plan:
CLBeaconRegion
continuez à surveiller, en arrière-plan ou au premier plan et gardez notifyEntryStateOnDisplay = YES
notifyEntryStateOnDisplay
appelle locationManager:didDetermineState:forRegion:
en arrière-plan, alors implémentez cet appel délégué ......comme ça:
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
if (state == CLRegionStateInside) {
//Start Ranging
[manager startRangingBeaconsInRegion:region];
}
else{
//Stop Ranging
[manager stopRangingBeaconsInRegion:region];
}
}
J'espère que ça aide.
Vous effectuez deux opérations distinctes ici - "balise" des balises et surveillance pour une région. Vous pouvez surveiller une région en arrière-plan, mais pas les balises de distance.
Par conséquent, votre implémentation de locationManager:didRangeBeacons:inRegion:
ne sera pas appelé en arrière-plan. Au lieu de cela, votre appel à startMonitoringForRegion
entraînera l'appel à une/certaines des méthodes suivantes:
– locationManager:didEnterRegion:
– locationManager:didExitRegion:
– locationManager:didDetermineState:forRegion:
Ceux-ci seront appelés en arrière-plan. Vous pouvez alors déclencher une notification locale, comme dans votre code d'origine.
Votre application devrait actuellement se réveiller si vous souhaitez simplement être averti lorsque vous entrez dans une région de balise. La seule restriction d'arrière-plan que je connaisse concerne l'hébergement d'un iBeacon sur un appareil iOS. Dans ce cas, l'application doit être physiquement ouverte au premier plan. Pour cette situation, vous feriez mieux de simplement implémenter directement CoreBluetooth CBPeripheralManager
. De cette façon, vous auriez des capacités publicitaires en arrière-plan.