I want to implement a feature on iOS to notify user when reach a special location (such as a bus station, don't miss it), it is easy if user always put app in foreground mode, using GPS location to detect whether arrived nearly or not. The key point is how to achieve it in background mode.
One possible solution is to update GPS in background mode, something like map navigation APP, but as you know GPS is power killer, user may not like it.
See CoreLocation API, found the following delegate callbacks, I am not sure whether they work well in background mode. Any idea on this topic please share and discuss together and thanks in advance.
- (void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region __OSX_AVAILABLE_STARTING(__MAC_10_7,__IPHONE_4_0);
- (void)locationManager:(CLLocationManager *)manager
didStartMonitoringForRegion:(CLRegion *)region __OSX_AVAILABLE_STARTING(__MAC_TBD,__IPHONE_5_0);
From the Location and Maps Programming Guide
In iOS, regions associated with your app are tracked at all times,
including when the app isn’t running. If a region boundary is crossed
while an app isn’t running, that app is relaunched into the background
to handle the event. Similarly, if the app is suspended when the event
occurs, it’s woken up and given a short amount of time (around 10
seconds) to handle the event. When necessary, an app can request more
background execution time using the
beginBackgroundTaskWithExpirationHandler: method of the UIApplication
class.
Related
I need support for iBeacon Technology. In our case, I want one feature of continuously scanning (Ranging) of iBeacons weather our app is in foreground or background. We know its possible with CLLocationManager standard update location methods. But we don’t want to go with standard Location Updates (As we don’t want to take risk of battery drain). Is there any other option to start continuous Ranging of CLBeaconRegion without using CLLocationManager?
I am using Estimote Beacons and there are delegate methods or Estimate SDK(ESTBeaconManager class) available "https://github.com/Estimote/iOS-SDK", whenever beacons come in range or goes out of range,below said delegate methods will be called internally and help us to reduce battery drain.We can place the proximity checks in didEnterRegion Method:
- (void)beaconManager:(ESTBeaconManager *)manager didEnterRegion:(ESTBeaconRegion *)region{}
- (void)beaconManager:(ESTBeaconManager *)manager didExitRegion:(ESTBeaconRegion *)region{}
- (void)beaconConnectionDidSucceeded:(ESTBeacon*)beacon{}
- (void)beaconConnectionDidFail:(ESTBeacon*)beacon withError:(NSError*)error{}
- (void)beaconManager:(ESTBeaconManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(ESTBeaconRegion *)region{}
The only way you can detect iBeacon transmissions on iOS is with CoreLocation, and you are correct that constant ranging does drain the battery significantly.
In theory you could use CoreBluetooth to detect other beacon types like AltBeacon (reading iBeacon advertisement details are blocked by CoreBluetooth), but battery usage would still be similar.
The standard way to save battery in the background is to use CoreLocation beacon monitoring APIs, which are easier on the battery. Then when a beacon is detected by these monitoring APIs, you can start ranging, even if your app is in the background.
For more info on extending background ranging time, see here: http://developer.radiusnetworks.com/2014/11/13/extending-background-ranging-on-ios.html
I came across this tutorial (http://www.appcoda.com/ios7-programming-ibeacons-tutorial/) about iBeacon which I found interesting. I've downloaded their source code and able to run well.
Anyway, I noticed one strange thing. There are times, when I run the broadcaster first instead of the receiver, the receiver seems to not be able to detect any beacon but if I run the receiver first, only then the beacon can be detected.
I've tried looking into other tuts but iBeacon seems like a new technology and not much reference can be found yet. Can any of you guys who had get their hands dirty into this iBeacon thing shed some light on this intermittent issue?
Your help are much appreciated.
The issue you're seeing is because the receiver app only starts 'ranging' for beacons if it detects that you have entered a region. If you start the broadcaster first, you're already inside the beacon's region, so your app might not start ranging. This sentence in the article is the clue:
Launch the receiver app and carry it far away from the broadcasting beacon and then walk towards it to simulate entering the region.
Monitoring for a beacon means that your app will only be notified when you enter or exit a region you've defined. The radius of this region could be up to ~50m, so if you're just sat next to the receiver, you shouldn't trigger one of these events unless you turn the receiver off and on again. Monitoring can be done whilst the app is running in the background or the foreground.
Ranging for beacons in a region means that the app will be notified once per second with a list of all beacons that the device can see in the specified region (ordered by distance). Ranging will call the locationManager:didRangeBeacons:inRegion: method of your CLLocationManager's delegate. The list of beacons will be constantly updated as you move around inside / outside the region and your distance to the beacons changes. Ranging is intended to happen whilst your app is in the foreground.
If you would like the app to continuously listen for beacons, try calling
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
in your viewDidLoad:, instead of in your didEnterRegion: method.
Its due to current location delegate available methods. Add this method also -
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
This will fix the issue.
I am working with two iOS devices, one is set up as an iBeacon.
I am ranging the beacon with a second iOS device and can grab its state via:
-(void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray *)beacons
inRegion:(CLBeaconRegion *)region{}
When I stop advertising on the iBeacon, the location manager on the second device continues to range/recognize the iBeacon for 5-10 seconds.
Is this expected behaviour?
Does the peripheralManager take time to wind down?
I have a setup with dedicated BTLE hardware running as iBeacons.
Actually it takes 20-30s to stop calling locationManager:didRangeBeacons:inRegion: and after that it calls locationManager:didExitRegion:
In my understanding it makes sense and it's exactly what CL is looking for because the device needs some time to make sure it really exited the region.
On the other hand, it starts ranging for beacons almost instantly after you fire the beacon up. There's no reason to wait to start ranging.
If you inspect the proximity property of the beacon you will notice that it's CLProximityUnknown during that time. Maybe you can do something with this state to do what you need.
I am working on project in which I need to fire notification when user reaches particular place, even application in background. What is the best way to do this?
What I found is following.
locationManager = [CLLocationManager new];
[locationManager startUpdatingLocation];
or
[sharedService.locationManager stopMonitoringSignificantLocationChanges];
or
[locationManager startMonitoringForRegion:region];
About startUpdatingLocation I am getting continuous notification on simulator and on ipod after 3-4 mins.
Documents says it will drain battery and appstore may not accept because this methods must be used by application like navigation types.
About stopMonitoringSignificantLocationChanges documents says it uses cellular network. I am not sure whether it wil work on ipod. On my ipod not working. Does this method needs sim card?
And how does this method works? Means should I walk some distance to get this method respond? I traveled 1-2 km but it did not work.
About startMonitoringForRegion I used
if([CLLocationManager regionMonitoringEnabled])
NSLog(#"monitering enable");
else
NSLog(#"monitering not avail");
For Ipod I got monitering not avail. Also client checked on his iphone. He also did not got notification.
Please can some one explain me this method? If any other way of finding location in background then please tell.
Edit:
I am using startUpdatingLocation. On device it calls didUpdateToLocation method every after 5 mins. Will it use lot of battery? and appstore will accept this?
If I use startUpdatingLocation will appstore accept app? Since my need is just to give notification when user reach a particular place.
According to the application requirement you describe I think that
- startMonitoringForRegion:
is the best approach, look at Apple Doc snippet below...
You can use the region-monitoring service to be notified when the user crosses a region-based boundary. Region monitoring applies both to geographical regions (represented by the CLCircularRegion class) and to beacon regions (represented by the CLBeaconRegion class). You region monitoring to detect boundary crossings of the specified region and you use those boundary crossings to perform related tasks. For example, upon approaching a dry cleaners, an app could notify the user to pick up any clothes that had been dropped off and are now ready.
You app is not tracking or routing related application so using [locationManager startUpdateLocation] will be overly done I think.
I would like to run a process in the background of my application that gets the user's current latitude/longitude (at 5 minute intervals) and reports it back to our server via web service call. When I add required background modes to my info.plist I have the following options:
-App plays audio
-App registers for location updates
-App provides Voice over IP services
Now in my case I obviously need the second choice on the list, but once I have the location what can I do with it? Can I make a web service call in the background?? What other limitations might there be??
Thanks a lot!
When you App is in background mode you can not establish a HTTP connection the usual way. You have to setup a background task that sends the location updates to your server.
I found a short tutorial that covers exactly what you're looking for (I've not tested the code).
This is a summary of how it works
When your App is running in background and a location change occurs, iOS wakes up your App and calls the delegate method locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation of your CLLocationManager. When this happens, check if your App is running in the background and setup the background task if it is. The background task then should send the data to your server.
Limitations
The documentation is not clear about how much time such a background task may take to finish, but I slightly remember it was something around 10 minutes maximum.
As far as I know you can not update the UI while your App runs in the
background