Chapter 11: Location Services: Know Where You Are

The ability to know the exact location of the device/user is arguably one of the main differentiating factors that set mobile programming apart from conventional web or native Mac development. That information about where your user is opens up a wealth of ideas and opportunities, and location-based services are arguably one of the hottest categories in the App Store.

The earliest location-based apps showed points of interest within your vicinity. Later, with the gyroscope hardware, some of these apps implemented augmented reality to show the same information. Another category of apps used location information to build a complete business around it—for example, foursquare and Facebook Places. The latest and hottest categories of location-based apps are the turn-by-turn navigation services and location-based reminders.

Apple came up with a couple of location-based apps, Find My Friends and Find My iPhone. Find My Friends helps you locate friends in your vicinity, and Find My iPhone can help you track a lost iDevice.

In this chapter, I briefly go through the basics of using location-based services in your app. Then, in the “Background Location” section I explain in detail the most important aspect of location services: getting a user’s location while your app is running in the background on his or her device. You also learn about managing the life of the device’s battery effectively.

Core Location Framework

Any iOS app that requires a user’s location needs to link with the Core Location framework (available as a part of the SDK). You can use classes and methods in this framework to get the location information on a user’s device.

If your application cannot function without location information (such as turn-by-turn navigation), you need to use the UIRequiredDeviceCapabilities key and add location-services or gps. This setting will ensure that the app cannot be installed on devices without those capabilities. UIRequiredDeviceCapabilities is discussed more in detail in Chapter 16.

If you were writing code directly on the hardware, getting the location of a device wouldn’t be an easy job. So far (at least as of this writing), no iOS device has shipped with a standalone/autonomous GPS chip. The GPS chip inside your iPhone or the 3G iPad is an assisted GPS (aGPS) chip that requires network data to calculate the location information of the device. (This is why you cannot locate yourself while roaming overseas with Data Roam disabled.) iOS uses a wealth of information including values from the assisted GPS chip, Wi-Fi and cell tower triangulation to calculate the location of the device. On devices without Wi-Fi (some iPhones sold in China have Wi-Fi disabled) or cellular network connectivity (all iPod touches and Wi-Fi-only iPads), iOS automatically uses other available information to calculate the location. However, location data obtained this way isn’t as precise.

The best part of Apple’s Core Location framework is that it abstracts you from all these complexities. Core Location framework provides a clean and elegant class that just reports the device’s location and accuracy when you ask for the location. You, as a developer, don’t have to deal with MAC addresses, cell tower signal strength, and so on.

Tapping into the User’s Location

Getting the user’s location with the Core Location framework is straightforward. You create an instance of CLLocationManager and call the startUpdatingLocation method.

Starting the Location Manager

locationManager = [[CLLocationManager alloc] init];

locationManager.delegate = self;

[locationManager startUpdatingLocation];

Optionally, you can set preferences in the CLLocationManager instance for the desired accuracy and the distance filter. You guessed it, a large distance filter and a coarse accuracy result in faster responses, whereas a narrow (or no) distance filter and a higher accuracy setting result in slower responses. iOS supports accuracy ranges from ten meters to three kilometers. Use them according to your application’s needs. For example, if you were writing a weather app, you probably wouldn’t need a very high accuracy. Weather information isn’t going to be different within a three-kilometer radius, which means you should consider using kCLLocationAccuracyThreeKilometers.

Getting the User’s Heading with the Built-In Compass

Similar to location, you can get the heading in which a user is traveling (or the direction that the device is pointed) using the Core Location framework. The built-in maps app rotates the map according to the direction users are facing so as to provide a better idea of exactly where they are. You can use heading in your own app in similar innovative ways. You can get heading information using the instance method startUpdatingHeading of CLLocationManager.

Getting Heading Updates

locationManager = [[CLLocationManager alloc] init];

locationManager.delegate = self;

[locationManager startUpdatingHeading];

You then conform to the CLLocationManagerDelegate protocol by implementing the methods below.

Location and Heading Delegates

- (void)locationManager:(CLLocationManager *)manager

    didUpdateToLocation:(CLLocation *)newLocation

           fromLocation:(CLLocation *)oldLocation {

  NSTimeInterval interval= [[newLocation timestamp] timeIntervalSinceNow];

  if(interval > -30 && interval < 0) {

    NSLog(@”%.4f, %.4f”, newLocation.coordinate.latitude,

    newLocation.coordinate.longitude);    

    [self.locationManager stopUpdatingLocation];

}

}

- (void)locationManager:(CLLocationManager *)manager

       didFailWithError:(NSError *)error {

  [self.locationManager stopUpdatingLocation];

  if([error code] != kCLErrorDenied) {

    //your code goes here

  }

  else {

    //Ask user to enable location

  }

}

Heading information is available only on devices with a built-in compass. Before using heading information, be sure to check for heading availability using [CLLocationManager headingAvailable]. Devices older than iPhone 3GS don’t have compass hardware to provide heading information.

The most important piece in this code to check is whether the location information you receive is new. iOS caches the last-known location and sends you that information first, along with the timestamp telling when it was cached. This cached location is shared across apps. For example, if the user is currently using a navigation app and opens your app, iOS already knows the location of the device and sends this information to your application; this information is sent to you almost immediately. But since this information might be stale, you should wait for more accurate and recent data. If you’re fine with the results, call stopUpdatingLocation.

Location Services and Privacy

For those writing software over the past decade, privacy has been a monumental concern. Web programmers have always been aware of the privacy issues associated with placing tracking cookies on a user’s computer, and now mobile programmers have their own list of similar concerns. In protecting users’ privacy, it’s important to let them know you want to access their location and then wait for their consent before accessing it. iOS shows a privacy alert to the users on your behalf and you have no control over it. So you might want to explain to users why you need access to their location.

Setting the Location Usage Description Text

The SDK allows developers to provide a “purpose” text stating why the app needs location information. iOS displays this information to users when asking for their consent, as illustrated in Figures 11-1 and 11-2.

9781118449974-fg1101.tif

Figure 11-1 Location Services dialog shown without a location usage description text

You set the purpose text in the Info.plist file for the key NSLocationUsageDescription. The CLLocationManager instance’s purpose text is deprecated in iOS 6 and you shouldn’t use that anymore. When you use location services, you need to consider setting this key in your Info.plist. The location usage description key helps users feel more comfortable in sharing their location with you.

Working Without Location Information

When asking a user for consent to use his location, it’s important to be on the watch for his denial. Your app must be able to handle this denial of consent and to work without location information. Failing to do so will result in your app being rejected by the app review team. The following code shows how to handle the denial of consent:

if([error code] != kCLErrorDenied) {

}

9781118449974-fg1102.tif

Figure 11-2 Location Services dialog showing the location usage description text

Other particular cases are when users have disabled location services altogether (for all apps) or when location services are disabled as a part of parental control restrictions. In either case, you need to check for location services availability and disable necessary UI elements if parental control restrictions disable use of location services. You can do that using the following code snippet:

if([CLLocationManager locationServicesEnabled]) {

  

}

Alternatively, if your application cannot work without location information, you should require it in the UIRequiredDeviceCapablities key.

Background Location

Prior to iOS 4, no third-party application could use location services when the app is not in the foreground. In fact, iOS 3 didn’t even support multitasking. Beginning with iOS 4, however, you have multiple ways to get location information when you’re running in the background.

You can get location updates continuously while running in the background, you can let the operating system notify you when a significant location change occurs, or you can monitor whether the device/user enters or exits a particular region. Which service you use is entirely application-dependent. However, as a developer, you should also be aware of how location updates can affect battery life. I explain about battery issues in the section, “Keeping an Eye on the Battery,” later in this chapter.

Getting Continuous Location Updates in the Background

Some apps, such as fitness trackers or apps that track your running and other workouts, need location information continuously in the background. If your application’s use case is similar, request iOS to let you access GPS information in the background by adding location to the UIBackgroundModes in your application’s Info.plist. Applications that require continuous location information are GPS-based fitness trackers and turn-by-turn navigation.

The GPS chip is easily one of the most power-hungry chips on the iPhone. Hence, using continuous location updates in background drains the battery quickly. If your app alerts the user about something when he “nears” a place or when he “leaves” a place, you should not use continuous background location. Apple provides another method to get updates when the user’s location changes significantly.

Subscribing to Significant Change Notification

Subscribing to significant location change is very similar to starting the location manager service you learnt in the previous section. You used startUpdatingLocation to get the device’s location. Instead of this method, you get significant location change notifications by calling the startMonitoringSignificantLocationChanges. For all other methods like the CLLocationManagereDelegate, setting the optional properties in CLLocationManager instance remains the same.

Significant location change monitoring will also bring your app to the foreground if it’s in the background. You can process the location information as though your app is in the foreground.

The significant location change API brings up some interesting app ideas, such as those in the following sections.

WeatherLah

Singapore is known for spontaneous showers throughout the year. Wouldn’t it be great if an app reminds you of an impending shower just before you move into a new location? Turns out, “There is an app for that.” WeatherLah is one among the list of the top 100 must-have apps in Singapore. What makes it unique and makes it stand out from other weather apps (including Apple’s weather app) is its innovative use of background location and crowd-sourced data. The screenshots in Figures 11-3 and 11-4 show two of the user interface’s important screens.

The iOS device monitors for significant location change and notifies the server of the latest location. When this location (or any location that you’re interested in) gets “enough” input from other users of the app that it’s raining, a push notification will be sent to you that it’s raining in the neighboring district.

foursquare Radar

foursquare introduced a feature called foursquare Radar that alerts you if you’re near some of the important locations that you are following. For example, you can “follow” a curated list such as “10 must-see places in Singapore,” and foursquare Radar will alert you when you are near one. You start the significant location service on iOS, send the location to the server whenever a significant change occurs, and send a push notification if the new location is near a place of interest.

9781118449974-fg1103.tif

Figure 11-3 Setting locations in WeatherLah

9781118449974-fg1104.tif

Figure 11-4 Gathering crowd-sourced data

Facebook Places

Facebook introduced a feature called Facebook Places that notifies you when a friend checks into a location near you. This feature, again, uses significant location changes. The iOS app registers for significant location changes and updates the server of the new location. The server sends a notification whenever a friend comes near your location.

From the examples in the preceding sections, you can see that just by using the significant location change API, you can build a product and a complete business using it. Next, I’ll show you yet another powerful feature called region monitoring provided by the Core Location framework.

Region Monitoring (Geo-Fencing)

In some cases, rather than being notified for every significant location change, your app might just require a notification when the user enters or exits a region. The Core Location framework provides APIs to monitor a region. Region monitoring is slightly trickier than the previous two techniques I described.

Gist

First, you create a region or an area of interest. This region could be one that’s specified by users or automatically calculated by your app based on the users’ input.

You create a region using the CLRegion class. The CLRegion class takes a center coordinate and a radius. As of iOS6, you can monitor only circular regions.

Creating a CLRegion and Monitoring It

CLRegion* region = [[CLRegion alloc] initCircularRegionWithCenter:overlay.coordinate

                     radius:radius identifier:identifier];

[self.locationManager startMonitoringForRegion:region

desiredAccuracy:kCLLocationAccuracyHundredMeters];

You then register this region and start region monitoring by implementing the delegate callbacks as follows:

Region Monitoring delegates

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion

    *)region;

- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion

    *)region;

These delegate methods will be called even when your app is in the background. In fact, your app will be brought to the foreground before the system calls this delegate.

Apple’s Reminders App

You can create reminders using Siri from iOS 5 using your location. That is, you can ask Siri to remind you to drop books at the library when you “leave the office.” What actually happens behind the scenes is that Siri picks up your office location from your “Me” card on the Contacts app and uses the coordinates to create a region. The Reminders app will now start monitoring that region for entry and exit events and will display a local notification when an exit event (didExitRegion:) is received.

iOS handles region monitoring and significant location changes internally using cell tower triangulation. To aggressively preserve battery life, iOS doesn’t turn on the GPS chip. Instead, region monitoring and significant location changes notifications are triggered when the tower that your device is connected to changes. Because cell towers are denser in cities and sparser in the outskirts, you might get more accurate notifications in a densely populated city than when you’re driving on a freeway. In my testing, I got a region-exited message only after I moved more than 100 kilometers away when I was driving across cities in Malaysia, though within Singapore, it’s much more accurate (in fact, it’s less than a kilometer). The same would be true for most countries.

Location Simulation

While I recommend using a device to test your location-based application, some apps (like a turn-by-turn navigation app) require the location to change while you test the app. The iOS Simulator allows you to simulate this navigation. You can turn this on from the menu option Debug⇒Location. You can also set Xcode to simulate a location using a scheme option. Choose the Edit Scheme⇒Run Action⇒Options tab to choose a location.

Additionally you can add a GPX file by creating one from File⇒New⇒File and choosing the GPX template from the resource section. When you have one or more GPX files, you can set Xcode to launch with a particular GPX file selected.

Keeping an Eye on the Battery

As a developer, you need to be aware of the battery life of your customers’ devices. If for some reason installing your app drains the battery, your users will promptly delete your app. To be a good citizen in the iOS land, use location services wisely. As I mentioned before, iOS is intelligent enough not to turn on the GPS chip unless it’s needed. Avoid setting the location string in UIBackgroundModes in your Info.plist. In most cases, when in the background, your app probably won’t need continuous location updates (as long as it isn’t a GPS-based fitness tracker or a turn-by-turn navigation app). Using a GPS fitness tracker on an iPhone 4S drains approximately 25 percent of the battery for a single run (that takes about 45 minutes), which is clearly not acceptable on any other app. Use significant location change or region monitoring as much as possible. This technique of getting location updates in the background drains little or no battery.

Secondly, when you register for region monitoring or significant location changes, avoid expensive network operations when your app is brought to the foreground. Network operations turn on the 3G chip, which further drains the battery.

Summary

In this chapter, you read about the ins and outs of location services. I explained the different methods that you can use to get location updates from a device. I also showed you how some of your commonly used apps use the background location feature to build useful features. Later, you discovered the pros and cons of every method and found out how to optimally use the battery on a user’s iDevice.

Further Reading

Apple Documentation

The following document is available in the iOS Developer Library at developer.apple.com or through the Xcode Documentation and API Reference.

Location Awareness Programming Guide

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.144.18