Getting GPS location, region in background on iOS4, iPhone 4By Mark on June 30th, 2010 in Technobabble
Tags: background, clregion, ios4, iphone 4, location, Write Ups
[UPDATE: This is the first post in a multi-post series on background location monitoring using iOS4.Â Check out the second post on cell tower triangulation and the third post, the resulting experiment .]
One of the more exciting new features of iOS4 is the new CLRegion class in Core Location, which lets the iPhone define geographical regions that your application can take an interest in.Â Then, iOS4 will run your application anytime the phone (i.e., you) leave or enter that region, even if your app wasn’t active when the event happens .Â Tell me that’s not awesome.Â It’s "wake-on-location".
CLRegion doesn’t work with the iPhone 3G or 3GS hardware, even if you’ve upgraded to iOS4 firmware.Â There is a workaround hack, though, which is detailed below in the "But I Have a 3G/3GS!" section.
How it Works
CLRegion objects work like this:
- Instantiate a
CLRegionwith a center coordinate and a distance/accuracy filter.
- Ask the
CLLocationManagerto begin monitoring for that region.
CLLocationManagerdelegate is called when you enter and exit a region.
The coolest part about this, though, is the background capability. When your phone is just sitting there, if you cross the boundary of a registered region (at present, you can only register circular regions), the phone will run app with the
location options flag set in the
applicationDidFinishLaunchingWithOptions: delegate method. Your application is then free to process the event.
We had an app idea to use this technology, but when I started to prototype, the new
regionMonitoringAvailable property kept returning NO on my 3GS.Â My first thought was that maybe I hadn’t initialized the
CLRegion object or Core Location properly, but after a bit of digging on Apple’s Developer Forums, the answer is that no, CLRegion is only available on iPhone 4 .Â This isn’t written anywhere on Apple’s developer documentation, and as far as I am concerned, heads should roll (there goes 2 hours).
But, the whole "unavailable" thing is not skulduggery on Apple’s part to try to get you to upgrade to iPhone 4, as I had first thought.Â It seems that the iPhone 4 packs completely new GPS hardware.
Apple’s 3G/3GS hardware is power-intensive – if the OS was consistently checking the location, even when the app was shut, you’d run out of battery relatively quickly; Apple will not enable this, and I support that.
However! There is a "workaround" if you have a 3G or 3GS; Apple included a new capability on the old hardware to help all of us out there who don’t always have the latest hardware.
But I Have a 3GS!
Even if the CLRegion hardware isn’t available, you still have an option for the wake-on-location feature.Â iOS4 also implements the
significantLocationChangeMonitoringAvailable property, which should be YES for the iPhone 3GS (not iPod Touch or iPhone 3G).
[Correction: I had previously posted that the 3G should respond YES to this method.Â I have since learned that this is only for the 3GS or iPhone 4.Â I have yet to test on the iPad. ]
The iPhone can still do background monitoring for significant location changes, but it relies "primarily" on your phone re-associating with a different cellular tower, according to the documentation .
The caveat here is that you cannot expect to be notified should you register a region that is physically close (depending on your cell tower signal strength, maybe 2km?) to your current location. You’d likely still be associated to the same cell tower even if you went to that new location, so the phone would never notify your application. Instead, the user would have to manually launch your app and check the location at that point (significantly less cool).
However, since that’s all I’ve got for my 3GS, I’ll take what I can get. So, to do this:
- Instantiate a
CLLocationManagerand ask for its blessing (make sure that
- Ask the
CLLocationManagerto begin monitoring for that region using
CLLocationManagerdelegate is called when there is a significant location change.
I’m in the process of implementing this code for my prototype, so if there is interest, I can repost the code when I have it working. Please let me know via the comments if you’re interested.
Hope this saves you the headache I had – well, maybe it’s time to upgrade to iPhone 4 anyway?
[UPDATE: I've received enough enquiries here and elsewhere that I've finally put in the effort to make some of the source code publicly available via an MIT-style license (=do whatever you want with it, but don't blame me, and include my copyright notice in the code if you change/redistribute/use). Please understand that we cannot offer the full Xcode project here as it's proprietary. The 2 classes included in the file are my CLLocationManager delegate class, and a logger class used to log events to a web server.]