Your mobile application should always leverage location data in some fashion, if possible. This may not always be applicable, but I think it goes a long way to enriching the end-user experience.
Location data types
For this post, I will focus on two broad types of location data: course and fine.
Network location is an example of course location data. Network location is typically one of the fastest types of data to obtain, but it is also one of the least accurate (unless connected to Wi-Fi). In my experience, network location accuracy can range from 500 meters to 2,500 meters (a mile is 1609.344 meters).
GPS is an example of fine location data. The big advantage of GPS data is accuracy (it can be as accurate as 5-10 meters), but you pay when it comes to speed. In some cases, it may take 2 - 5 minutes to get a first lock on GPS data.
The security models between iOS and Android are quite different when it comes to requesting location information.
With iOS, once the user grants your application privileges, the app may use the GPS hardware at its discretion. The user may revoke these privileges at any time, but the app has access to GPS whenever it wants, as long as the user has granted the app permission. (This is the extent of my knowledge about location data in iOS.)
In Android, applications are not allowed to programmatically turn on and turn off the GPS hardware. I believe this change was made in version 1.5 (Cupcake) to keep applications from draining unnecessary battery. We must account for this in application development and choose which location provider to use on the fly based upon some criteria, which I offer tips about below.
Choosing the best provider
There are several ways to choose the best provider. One is to call:
LocationManager.getBestProvider( Criteria criteria, boolean enabledOnly )
You may define your own criteria, including power requirement, accuracy, bearing, speed, and altitude, and the OS will return the provider that best matches those specifications. According to the documentation, if no providers are found, the criteria will be loosened in sequence of the items listed previously.
Another option is to manually cycle through all of the providers, get the last known location for each, and determine which location to use based upon your tests. To get a list of providers to cycle through, you could call:
LocationManager.getProviders( boolean enabledOnly )
Getting the last known location
We are living in what I like to call “the age of instant gratification.” Because of this, apps must be fast, responsive, and keep the end user waiting as little as possible. As I explained before, you may request a last known location from any location provider; the Android OS keeps track of a device’s last 50 locations, so this is by far the quickest way to get location data and continue on in the app.
To get the last known location for any provider, you can call:
LocationManager.getLastKnownLocation( String provider )
It is highly recommended that you check the “staleness” of this location to determine if you should request a new one. For the sake of speed, it will suffice to use it and move along. In one of my own solutions, I use the last known location to fetch a list of items server-side, and also to provide the user a mechanism for requesting a new location in case they determine the distances in the list of items returned are inaccurate.
Requesting a new location
Let’s say you want to request a new location from the OS, use it, and move on. For this, you would use:
LocationManager.requestSingleUpdate( String provider, PendingIntent intent )
If you’d like to continue receiving location updates, you may call:
LocationManager.requestLocationUpdates( String provider, long minTime, float minDistance, LocationListener listener)
In my experience, using a LocationListener is great when used from inside an Activity. This may represent a use case where you want to continue receiving location updates while the Activity is active, but wish to stop once the user has closed the app or moved on to another activity in your application.
For more long-term location tracking, I suggest you use the variation of requestLocationUpdates that uses a PendingIntent rather than a LocationListener to notify your app of updates. The advantage of using a PendingIntent is that you can set up a BroadcastReceiver in your manifest file to handle the PendingIntent. So without your app ever opening back up in the foreground, you can continue to receive location updates in the background, handle it accordingly, and wait until the next one comes along.
If you want to stop requesting location updates at some point, you can call:
LocationManager.removeUpdates( LocationListenerer listener )
I have only scratched the surface when it comes to leveraging location data on a mobile device. In a future post, I will discuss using location data in HTML5, proximityAlerts in Android, and a passive location provider in Android.