How to get paired bluetooth devices - ios

I want to create one application that show me paired devices in my app.(for example any device that paired me before detect and show me.)
also in the next time I want to send one NSString like "hello" to paired device.
I searching in google and I got so confused!!!
Please tell me first how to get paired device with my mobile and second how to send NSString value to them.

Here is an exemple for what you need :
You have to adapt it to match what u want. But you can see how it work ...
#implementation ViewController
{
CBPeripheralManager *_peripheralManager;
BOOL _isAdvertising;
}
- (void)_startAdvertising
{
NSUUID *estimoteUUID = [[NSUUID alloc] initWithUUIDString:#"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:estimoteUUID
major:2
minor:1
identifier:#"SimEstimote"];
NSDictionary *beaconPeripheralData = [region peripheralDataWithMeasuredPower:nil];
[_peripheralManager startAdvertising:beaconPeripheralData];
}
- (void)_updateEmitterForDesiredState
{
if (_peripheralManager.state == CBPeripheralManagerStatePoweredOn)
{
// only issue commands when powered on
if (_isAdvertising)
{
if (!_peripheralManager.isAdvertising)
{
[self _startAdvertising];
}
}
else
{
if (_peripheralManager.isAdvertising)
{
[_peripheralManager stopAdvertising];
}
}
}
}
#pragma mark - CBPeripheralManagerDelegate
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
[self _updateEmitterForDesiredState];
}
#pragma mark - Actions
- (IBAction)advertisingSwitch:(UISwitch *)sender
{
_isAdvertising = sender.isOn;
[self _updateEmitterForDesiredState];
}
#end
This for monitoring :
#implementation AppDelegate
{
CLLocationManager *_locationManager;
BOOL _isInsideRegion; // flag to prevent duplicate sending of notification
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)options
{
// create a location manager
_locationManager = [[CLLocationManager alloc] init];
// set delegate, not the angle brackets
_locationManager.delegate = self;
NSUUID *estimoteUUID = [[NSUUID alloc] initWithUUIDString:#"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:estimoteUUID
identifier:#"Estimote Range"];
// launch app when display is turned on and inside region
region.notifyEntryStateOnDisplay = YES;
if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
[_locationManager startMonitoringForRegion:region];
// get status update right away for UI
[_locationManager requestStateForRegion:region];
}
else
{
NSLog(#"This device does not support monitoring beacon regions");
}
// Override point for customization after application launch.
return YES;
}
- (void)_sendEnterLocalNotification
{
if (!_isInsideRegion)
{
UILocalNotification *notice = [[UILocalNotification alloc] init];
notice.alertBody = #"Inside Estimote beacon region!";
notice.alertAction = #"Open";
[[UIApplication sharedApplication] scheduleLocalNotification:notice];
}
_isInsideRegion = YES;
}
- (void)_sendExitLocalNotification
{
if (_isInsideRegion)
{
UILocalNotification *notice = [[UILocalNotification alloc] init];
notice.alertBody = #"Left Estimote beacon region!";
notice.alertAction = #"Open";
[[UIApplication sharedApplication] scheduleLocalNotification:notice];
}
_isInsideRegion = NO;
}
- (void)_updateUIForState:(CLRegionState)state
{
ViewController *vc = (ViewController *)self.window.rootViewController;
if (state == CLRegionStateInside)
{
vc.label.text = #"Inside";
}
else if (state == CLRegionStateOutside)
{
vc.label.text = #"Outside";
}
else
{
vc.label.text = #"Unknown";
}
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
// always update UI
[self _updateUIForState:state];
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
{
// don't send any notifications
return;
}
if (state == CLRegionStateInside)
{
[self _sendEnterLocalNotification];
}
else
{
[self _sendExitLocalNotification];
}
}
#end
You can have the complete description at this adress :
http://www.cocoanetics.com/2013/11/can-you-smell-the-ibeacon/

Related

Inconsistent behaviour by proximity API - iOS iBeacon

I am converting an iOS device into iBeacon and then using core location' ranging API to detect beacon' proximity. Now, this works but I see an unpredictable behaviour where sometimes at a defined distance (say 10 meters away) I see No Beacon sometimes Far Beacon and some times Near Beacon.
Is there a way to make this behaviour more consistent?
- (void)viewDidLoad {
[super viewDidLoad];
self.beaconSwitch.on = NO;
self.beaconView.backgroundColor = [UIColor clearColor];
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
BeaconRegion *beaconRegion = [[BeaconRegion alloc] init];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beaconRegion.uuid major:[beaconRegion.major shortValue] minor:[beaconRegion.minor shortValue] identifier:beaconIdentifier];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.peripheralManager stopAdvertising];
}
- (IBAction)doneButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)beaconSwitchPressed:(id)sender {
if (self.beaconSwitch.on == true) {
self.beaconView.beaconState = BNBeaconStateBroadcasting;
NSDictionary *data = [self.beaconRegion peripheralDataWithMeasuredPower:nil];
[self.peripheralManager startAdvertising:data];
} else {
self.beaconView.beaconState = BNBeaconStateStop;
[self.peripheralManager stopAdvertising];
}
}
Here is how I am converting my iOS device into a beacon:
And here is how I am getting its proximity:
- (void)viewDidLoad {
[super viewDidLoad];
BeaconRegion *beaconRegion = [[BeaconRegion alloc] init];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beaconRegion.uuid identifier:beaconIdentifier];
self.beaconRegion.notifyOnEntry = YES;
self.beaconRegion.notifyOnExit = YES;
self.beaconRegion.notifyEntryStateOnDisplay = YES;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.detectionSwitch.on = NO;
}
- (IBAction)beaconDetectionSwitchPressed:(id)sender {
if (self.detectionSwitch.isOn) {
[self.locationManager startMonitoringForRegion:self.beaconRegion];
[self.locationManager requestStateForRegion:self.beaconRegion];
} else {
self.lastProximity = CLProximityUnknown;
[self.locationManager stopMonitoringForRegion:self.beaconRegion];
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
self.titleLabel.text = #"";
self.messageLabel.text = #"";
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.locationManager stopMonitoringForRegion:self.beaconRegion];
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
self.locationManager = nil;
}
- (void)locationManager:(CLLocationManager *)iManager didEnterRegion:(CLRegion *)iRegion {
NSLog(#"Detected a beacon");
if (![self.beaconRegion isEqual:iRegion]) {
return;
}
NSLog(#"Entered into the beacon region = %#", iRegion);
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
NSLog(#"Ranging beacon successful");
if (beacons.count > 0) {
CLBeacon *nearestBeacon = beacons[0];
CLProximity currentProximity = nearestBeacon.proximity;
if (currentProximity == self.lastProximity) {
NSLog(#"No Change in Beacon distance");
} else {
self.lastProximity = currentProximity;
[self updateUserAboutProximity];
}
} else {
self.lastProximity = CLProximityUnknown;
}
}
- (void)updateUserAboutProximity {
NSString *title = #"--";
NSString *message = #"--";
switch (self.lastProximity) {
case CLProximityUnknown:{
title = #"No Beacon";
message = #"There is no nearby beacon";
}
break;
case CLProximityImmediate:{
title = #"Immediate Beacon";
message = #"You are standing immediate to video wall!";
}
break;
case CLProximityNear:{
if (self.isServerCallOn) {
title = #"Near Beacon";
message = #"You are standing near to video wall!";
} else {
title = #"Near Beacon";
message = #"You are standing near to video wall! Initiating a server call.";
if (!self.ignoreSeverCallTrigger) {
self.isServerCallOn = YES;
[self talkToServer];
} else {
NSLog(#"Ignoring server call trigger");
message = #"Ignoring server call trigger!";
}
}
}
break;
case CLProximityFar:{
title = #"Far Beacon";
message = #"You are standing far from video wall!";
}
break;
default:
break;
}
self.titleLabel.text = title;
self.messageLabel.text = message;
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if (state == CLRegionStateInside) {
NSLog(#"Starting Ranging");
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (![CLLocationManager locationServicesEnabled]) {
NSLog(#"Location Service Not Enabled");
}
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways) {
NSLog(#"Location Service Not Authorized");
}
}
For now, I have put a condition on received signal strength indicator (rssi) value and accepting anything > -60 in Near proximity to make the distance little more predictable. So, within Nearby proximity also I trigger my action if rssi > -60.

CLRegion background monitoring not occuring

In my project settings > target > Capabilities I have Background Modes ON with "Location Updates" checked.
AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.storyController = [StoryController sharedController];
self.storyController.locationManager.delegate = self;
... etc initializing VC ...
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(#"entered region, %#", region.identifier);
[self handleRegionEvent:region];
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(#"exited region, %#", region.identifier);
[self handleRegionEvent:region];
}
- (void)handleRegionEvent:(CLRegion *)region {
NSLog(#"handle region");
if ([UIApplication sharedApplication].applicationState ==
UIApplicationStateActive) {
NSLog(#"handle region local");
UILocalNotification *n = [[UILocalNotification alloc] init];
n.alertBody = #"LOCAL";
n.soundName = #"Default"; //Coffee Man?
[[UIApplication sharedApplication] presentLocalNotificationNow:n];
} else {
if ([[StoryController sharedController] readyForNextChapter]) {
UILocalNotification *n = [[UILocalNotification alloc] init];
n.alertBody = #"New ☕ Story";
n.soundName = #"Default"; //Coffee Man?
[[UIApplication sharedApplication] presentLocalNotificationNow:n];
}
}
}
StoryController
+ (id)sharedController {
static StoryController *myController = nil;
static dispatch_once_t token;
dispatch_once(&token, ^{
myController = [[StoryController alloc] init];
});
return myController;
}
- (id)init {
self = [super init];
self.locationManager = [[CLLocationManager alloc] init];
NSLog(#"monitored regions: %#", self.locationManager.monitoredRegions);
I am monitoring for the region later on with:
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:g.coordinate radius:1000 identifier:"My Store"];
region.notifyOnEntry = true;
region.notifyOnExit = true;
NSLog(#"%d", [CLLocationManager authorizationStatus]);
[[[StoryController sharedController] locationManager] startMonitoringForRegion:region];
I am not receiving any notifications when I leave or enter a 1km range with the app backgrounded.
How do I make this work? When I log out my monitored regions, I do see the lat & lng are correct.
Two things you need to make sure you're doing.
checking for availability of region monitoring
make sure your locationManager.authorizationStatus == .authorizedAlways
Some systems simply don't support region monitoring, and region monitoring will never work unless your authorizationStatus is .authorizedAlways, only then can it monitor in the background.
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html

Unable to detect ibeacon on iphone 6

Hi i have below code which works fine on iPod touch 5, but same code is not working on iPhone 6, i done research on same issue but i have not found anything useful. both devices have latest iOS.
Both devices have iOS 8
// MapViewController.m
// SidebarDemo
//
// Created by Simon on 30/6/13.
// Copyright (c) 2013 Appcoda. All rights reserved.
//
#import "PetFinderViewController.h"
#import "SWRevealViewController.h"
#interface PetFinderViewController ()
#end
#implementation PetFinderViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithRed:(51/255.0) green:(51/255.0) blue:(51/255.0) alpha:1] ;
self.title = #"Pet Finder";
// Change button color
//_sidebarButton.tintColor = [UIColor colorWithWhite:0.96f alpha:0.2f];
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
_sidebarButton.target = self.revealViewController;
_sidebarButton.action = #selector(revealToggle:);
// Set the gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
// Check if beacon monitoring is available for this device
if (![CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Monitoring not available" message:nil delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil]; [alert show]; return;
}
else
{
// Initialize location manager and set ourselves as the delegate
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Create a NSUUID
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"ebefd083-70a2-47c8-9837-e7b5634df524"];
// Setup a new region AND start monitoring
str_beaconIdentifier = #"in.appstute.marketing";
self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:1 minor:1 identifier:str_beaconIdentifier];
self.myBeaconRegion.notifyEntryStateOnDisplay = YES;
self.myBeaconRegion.notifyOnEntry = YES;
self.myBeaconRegion.notifyOnExit = YES;
[self.locationManager startMonitoringForRegion:self.myBeaconRegion];
self.lbl_rangeStatus.text = #"Finding Your Pet";
self.lbl_regionStatus.text = #"";
self.lbl_distance.text = #"";
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
if (![CLLocationManager locationServicesEnabled]) {
NSLog(#"Couldn't turn on ranging: Location services are not enabled.");
}
if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorized) {
NSLog(#"Couldn't turn on monitoring: Location services not authorised.");
[self.locationManager requestAlwaysAuthorization];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Core Location Delegate methods
- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion *)region
{
UILocalNotification *notify = [[UILocalNotification alloc] init];
notify.alertBody = #"You are near your Pet's region.";
notify.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notify];
// We entered a region, now start looking for our target beacons!
//self.statusLabel.text = #"Finding beacons.";
self.lbl_rangeStatus.text = #"Pet Found";
self.lbl_regionStatus.text = #"Status : Entered Region";
[self.locationManager startRangingBeaconsInRegion:self.myBeaconRegion];
//Opening camera
/*if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.allowsEditing = YES;
//[self presentModalViewController:imagePicker animated:YES];
[self presentViewController:imagePicker animated:YES completion:nil];
}
else
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Camera Unavailable"
message:#"Unable to find a camera on your device."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[alert show];
alert = nil;
}*/
}
-(void)locationManager:(CLLocationManager*)manager didExitRegion:(CLRegion *)region
{
UILocalNotification *notify = [[UILocalNotification alloc] init];
notify.alertBody = #"You are far away from your Pet's region.";
notify.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notify];
// Exited the region
//self.statusLabel.text = #"None found.";
self.lbl_rangeStatus.text = #"Pet Not Found";
self.lbl_regionStatus.text = #"Status : Exited Region";
[self.locationManager stopRangingBeaconsInRegion:self.myBeaconRegion];
}
-(void)locationManager:(CLLocationManager*)manager didRangeBeacons:(NSArray*)beacons inRegion:(CLBeaconRegion*)region
{
CLBeacon *foundBeacon = [beacons firstObject];
// Retrieve the beacon data from its properties
NSString *uuid = foundBeacon.proximityUUID.UUIDString;
NSString *major = [NSString stringWithFormat:#"%#", foundBeacon.major];
NSString *minor = [NSString stringWithFormat:#"%#", foundBeacon.minor];
NSLog(#"uuid=%#, major=%#, minor=%#",uuid, major, minor);
self.lbl_regionStatus.text = #"Status : Entered Region";
if(foundBeacon.proximity==CLProximityImmediate)
{
NSLog(#"Immediate");
//self.Lb_proxomity.text = #"Immediate";
}
else if (foundBeacon.proximity==CLProximityNear)
{
NSLog(#"Near");
//self.Lb_proxomity.text = #"Near";
}
else if(foundBeacon.proximity==CLProximityFar)
{
NSLog(#"Far");
//self.Lb_proxomity.text = #"Far";
}
else if(foundBeacon.proximity==CLProximityUnknown)
{
NSLog(#"Unknown");
//self.Lb_proxomity.text = #"Unknown";
}
float actualDistance = foundBeacon.accuracy/10;
NSLog(#"Distance = %f",actualDistance);
if(actualDistance >= 0.0)
{
self.lbl_distance.text = [NSString stringWithFormat:#"Distance : %.2f m",actualDistance];
}
//self.Lb_meter.text = [NSString stringWithFormat:#"%.2f",foundBeacon.accuracy];
//self.Lb_centimeter.text = [NSString stringWithFormat:#"%.2f",(foundBeacon.accuracy*100)];
//[self presentExhibitInfoWithMajorValue:foundBeacon.major.integerValue];
//Calling this method to display strength for distance between user and the pet
[self fn_showStrengthForDistanceBetweenUserAndPet:actualDistance];
}
#pragma mark - Check Background App Refresh status
-(BOOL)CanDeviceSupportAppBackgroundRefresh
{
// Override point for customization after application launch.
if ([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusAvailable) {
NSLog(#"Background updates are available for the app.");
return YES;
}else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusDenied)
{
NSLog(#"The user explicitly disabled background behavior for this app or for the whole system.");
return NO;
}else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted)
{
NSLog(#"Background updates are unavailable and the user cannot enable them again. For example, this status can occur when parental controls are in effect for the current user.");
return NO;
}
return NO;
}
#pragma mark - Check if monitoring region failed
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
NSLog(#"monitoringDidFailForRegion - error: %#", [error localizedDescription]);
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLBeaconRegion *)region{
if (state == CLRegionStateInside) {
//Start Ranging
[manager startRangingBeaconsInRegion:region];
}
else{
//Stop Ranging
[manager stopRangingBeaconsInRegion:region];
}
}
#end
I suspect you are having authorization issues on your iPhone. Set a breakpoint or add NSLog statements to make sure this line is getting called:
[self.locationManager requestAlwaysAuthorization];
Do you get prompted? If not, uninstall and reinstall.
Also, check in setting that Bluetooth and Location services are enabled on the phone, and check settings on your app to see that location services are actually enabled for it.
You need to set one of
NSLocationAlwaysUsageDescription
or
NSLocationWhenInUseUsageDescription when requesting location updates (even with iBeacons).
If you don't, in iOS 8, this will fail silently.

Getting location updates when app is inactive stops after 2 updates

I'm trying to get location updates while my app is inactive (user closed the app).
After 2 location updates, the location updates stops launching my app.
Indicator for this is the gray arrow in my app in location services settings.
What I'm trying is combination of startMonitoringSignificantLocationChanges & regionMonitoring.
I tested on iPhone 4 iOS 7.1.1 and location updates stops after 2 updates.
I tested in iPad mini WiFi+Cellular iOS 7.1.1 and location updates stops after 1 update and region monitoring send only 1 location.
Where I'm wrong?
My code:
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
[RegionMonitoringService sharedInstance].launchOptions = launchOptions;
[[RegionMonitoringService sharedInstance] stopMonitoringAllRegions];
if ( [CLLocationManager significantLocationChangeMonitoringAvailable] ) {
[[RegionMonitoringService sharedInstance] startMonitoringSignificantLocationChanges];
} else {
NSLog(#"Significant location change service not available.");
}
if (launchOptions[UIApplicationLaunchOptionsLocationKey]) {
[self application:application handleNewLocationEvet:launchOptions]; // Handle new location event
UIViewController *controller = [[UIViewController alloc] init];
controller.view.frame = [UIScreen mainScreen].bounds;
UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:controller];
dispatch_async(dispatch_get_main_queue(), ^{
appDelegate.window.rootViewController = nvc;
[appDelegate.window makeKeyAndVisible];
});
}
else {
// ...
}
return YES;
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[defaults synchronize];
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
if ([RegionMonitoringService sharedInstance].launchOptions[UIApplicationLaunchOptionsLocationKey]) {
return;
}
}
- (void)application:(UIApplication *)application handleNewLocationEvet:(NSDictionary *)launchOptions
{
NSLog(#"%s, launchOptions: %#", __PRETTY_FUNCTION__, launchOptions);
if (![launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) return;
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) return;
SendLocalPushNotification(#"handleNewLocationEvet");
}
RegionMonitoringService.h:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import "ServerApiManager.h"
#interface RegionMonitoringService : NSObject
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) NSDictionary *launchOptions;
#property (strong, nonatomic) NSDate *oldDate;
#property (strong, nonatomic) CLLocation *oldLocation;
+ (RegionMonitoringService *)sharedInstance;
- (void)startMonitoringForRegion:(CLRegion *)region;
- (void)startMonitoringRegionWithCoordinate:(CLLocationCoordinate2D)coordinate andRadius:(CLLocationDirection)radius;
- (void)stopMonitoringAllRegions;
- (void)startMonitoringSignificantLocationChanges;
- (void)stopMonitoringSignificantLocationChanges;
FOUNDATION_EXPORT NSString *NSStringFromCLRegionState(CLRegionState state);
#end
RegionMonitoringService.m:
#import "RegionMonitoringService.h"
static CLLocationDistance const kFixedRadius = 250.0;
#interface RegionMonitoringService () <CLLocationManagerDelegate>
- (NSString *)identifierForCoordinate:(CLLocationCoordinate2D)coordinate;
- (CLLocationDistance)getFixRadius:(CLLocationDistance)radius;
- (void)sortLastLocation:(CLLocation *)lastLocation;
#end
#implementation RegionMonitoringService
+ (RegionMonitoringService *)sharedInstance
{
static RegionMonitoringService *_sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
- (instancetype)init
{
self = [super init];
if (!self) {
return nil;
}
_locationManager = [[CLLocationManager alloc] init];
_locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
_locationManager.distanceFilter = kCLDistanceFilterNone;
// _locationManager.activityType = CLActivityTypeFitness;
_locationManager.delegate = self;
return self;
}
- (void)startMonitoringForRegion:(CLRegion *)region
{
NSLog(#"%s", __PRETTY_FUNCTION__);
[_locationManager startMonitoringForRegion:region];
}
- (void)startMonitoringRegionWithCoordinate:(CLLocationCoordinate2D)coordinate andRadius:(CLLocationDirection)radius
{
NSLog(#"%s", __PRETTY_FUNCTION__);
if (![CLLocationManager regionMonitoringAvailable]) {
NSLog(#"Warning: Region monitoring not supported on this device.");
return;
}
if (__iOS_6_And_Heigher) {
CLRegion *region = [[CLRegion alloc] initCircularRegionWithCenter:coordinate
radius:radius
identifier:[self identifierForCoordinate:coordinate]];
[_locationManager startMonitoringForRegion:region];
}
else {
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:coordinate
radius:radius
identifier:[self identifierForCoordinate:coordinate]];
[_locationManager startMonitoringForRegion:region];
}
SendLocalPushNotification([NSString stringWithFormat:#"StartMonitor: {%f, %f}", coordinate.latitude, coordinate.longitude]);
}
- (void)stopMonitoringAllRegions
{
NSLog(#"%s", __PRETTY_FUNCTION__);
if (_locationManager.monitoredRegions.allObjects.count > 1) {
for (int i=0; i<_locationManager.monitoredRegions.allObjects.count; i++) {
if (i == 0) {
NSLog(#"stop monitor region at index %d", i);
CLRegion *region = (CLRegion *)_locationManager.monitoredRegions.allObjects[i];
[_locationManager stopMonitoringForRegion:region];
}
}
}
}
- (void)startMonitoringSignificantLocationChanges
{
NSLog(#"%s", __PRETTY_FUNCTION__);
[_locationManager startMonitoringSignificantLocationChanges];
}
- (void)stopMonitoringSignificantLocationChanges
{
NSLog(#"%s", __PRETTY_FUNCTION__);
[_locationManager stopMonitoringSignificantLocationChanges];
}
- (NSString *)identifierForCoordinate:(CLLocationCoordinate2D)coordinate
{
NSLog(#"%s", __PRETTY_FUNCTION__);
return [NSString stringWithFormat:#"{%f, %f}", coordinate.latitude, coordinate.longitude];
}
FOUNDATION_EXPORT NSString *NSStringFromCLRegionState(CLRegionState state)
{
NSLog(#"%s", __PRETTY_FUNCTION__);
if (__iOS_6_And_Heigher) {
return #"Support only iOS 7 and later.";
}
if (state == CLRegionStateUnknown) {
return #"CLRegionStateUnknown";
} else if (state == CLRegionStateInside) {
return #"CLRegionStateInside";
} else if (state == CLRegionStateOutside) {
return #"CLRegionStateOutside";
} else {
return [NSString stringWithFormat:#"Undeterminded CLRegionState"];
}
}
- (CLLocationDistance)getFixRadius:(CLLocationDistance)radius
{
if (radius > _locationManager.maximumRegionMonitoringDistance) {
radius = _locationManager.maximumRegionMonitoringDistance;
}
return radius;
}
- (void)sortLastLocation:(CLLocation *)lastLocation
{
NSLog(#"%s, %#", __PRETTY_FUNCTION__, lastLocation);
self.oldDate = lastLocation.timestamp; // Get new date
NSTimeInterval seconds = fabs([self.oldLocation.timestamp timeIntervalSinceDate:self.oldDate]); // Calculate how seconds passed
NSInteger minutes = seconds * 60; // Calculate how minutes passed
if (lastLocation && self.oldLocation) { // New & old location are good
if ([lastLocation distanceFromLocation:self.oldLocation] >= 200 || minutes >= 30) { // Distance > 200 or 30 minutes passed
[[ServerApiManager sharedInstance] saveLocation:lastLocation]; // Send location to server
}
}
else { // We just starting location updates
[[ServerApiManager sharedInstance] saveLocation:lastLocation]; // Send new location to server
}
self.oldLocation = lastLocation; // Set old location
}
#pragma mark - CLLocationManagerDelegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"%s, %#", __PRETTY_FUNCTION__, locations);
CLLocation *lastLocation = (CLLocation *)locations.lastObject;
CLLocationCoordinate2D coordinate = lastLocation.coordinate;
if (lastLocation == nil || coordinate.latitude == 0.0 || coordinate.longitude == 0.0) {
return;
}
[self startMonitoringRegionWithCoordinate:coordinate andRadius:[self getFixRadius:kFixedRadius]];
[self sortLastLocation:lastLocation];
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region
{
NSLog(#"%s, currentLocation: %#, regionState: %#, region: %#",
__PRETTY_FUNCTION__, manager.location, NSStringFromCLRegionState(state), region);
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region
{
NSLog(#"%s, REGION: %#", __PRETTY_FUNCTION__, region);
[manager requestStateForRegion:region];
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(#"%s, REGION: %#", __PRETTY_FUNCTION__, region);
[self stopMonitoringAllRegions];
[self startMonitoringRegionWithCoordinate:manager.location.coordinate andRadius:[self getFixRadius:kFixedRadius]];
CLLocation *lastLocation = manager.location;
CLLocationCoordinate2D coordinate = lastLocation.coordinate;
if (lastLocation == nil || coordinate.latitude == 0.0 || coordinate.longitude == 0.0) {
return;
}
[self sortLastLocation:manager.location];
}
#end
EDIT 1:
I did a a lot of real time tests with car with several devices (iPhone 5s, iPad mini, iPhone 4) after several tests I came to this:
In one case, iPad mini & iPhone 4 stops updating location after several minutes when app is not running and the little arrow become gray.
When WiFi was off, the accuracy was terrible and locations updated rarely.
EDIT 2:
OK, after a lot of driving and walking around and testing it it works like a charm so far.
I managed to make it work, combining significantLocationChanges & region monitoring, always register a geofence around my current location and always starting significant location changes when new UIApplicationLaunchOptionsLocationKey come.
Note that turning off wifi make accuracy very low and even sometimes not working.
Any bugs in my code?
From the Apple docs it can be seen that updates are not sent more frequently than every 5 minutes and for 500 meters of location change:
Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
You are going to receive the updates even when the app is inactive. Another hint for you might be that oyu can test the location in the simulator instead using a real device, this way you don't have to go outside for testing and can still check your logs too. In the simulator menu, chose Debug --> Location.

iBeacon and Notification

i'm developing an iOS application and i'm using beacons.
I've a problem. I'm at the beginning of the development, so I only have my appdelegate. In appdelegate.m I have initialized like so
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"8AEFB031-6C32-486F-825B-E26FA193487D"];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:#"Region"];
if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
NSLog(#"I'm looking for a beacon");
[self.locationManager startRangingBeaconsInRegion:region];
} else {
NSLog(#"Device doesn't support beacons ranging");
}
return YES;
}
and then I wrote two delegate methods
- (void) locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(#"EXIT");
}
- (void) locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(#"ENTER");
}
but they never get called!!! What's the problem here?
you RANGE but you never MONITOR the regions.
Ranging for beacons will only call: locationManager:didRangeBeacons:inRegion:
The methods enterRegion/exitRegion you want are for monitoring only. So call:
- (void)startMonitoringForRegion:(CLRegion *)region
I don't know why there are not calling but this is how we can handle beacons...
- (void)createBeaconRegion
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"8AEFB031-6C32-486F-825B-E26FA193487D"];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:#"Region"];
if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
NSLog(#"I'm looking for a beacon");
[self.locationManager startRangingBeaconsInRegion:region];
} else {
NSLog(#"Device doesn't support beacons ranging");
}
}
- (void)turnOnRanging
{
NSLog(#"Turning on ranging...");
if (![CLLocationManager isRangingAvailable]) {
NSLog(#"Couldn't turn on ranging: Ranging is not available.");
self.rangingSwitch.on = NO;
return;
}
if (self.locationManager.rangedRegions.count > 0) {
NSLog(#"Didn't turn on ranging: Ranging already on.");
return;
}
[self createBeaconRegion];
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
NSLog(#"Ranging turned on for region: %#.", self.beaconRegion);
}
- (void)startRangingForBeacons
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.detectedBeacons = [NSArray array];
[self turnOnRanging];
}
- (void)stopRangingForBeacons
{
if (self.locationManager.rangedRegions.count == 0) {
NSLog(#"Didn't turn off ranging: Ranging already off.");
return;
}
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
NSLog(#"Turned off ranging.");
}
You can refer the entire sample project using below link
https://github.com/nicktoumpelis/HiBeacons
That uses to display Beacons..
Hope it helps you....!

Resources