Stats

411 Contributors: 10 Tuesday, May 30, 2017
Licensed under: CC-BY-SA
Not affiliated with Stack Overflow
Rip Tutorial: riptutorial@gmail.com
Roadmap: roadmap

Location

Introduction

Android Location APIs are used in a wide variety of apps for different purposes such as finding user location, notifying when a user has left a general area (Geofencing), and help interpret user activity (walking, running, driving, etc).

However, Android Location APIs are not the only means of acquiring user location. The following will give examples of how to use Android's LocationManager and other common location libraries.

Remarks

For building Location aware apps in Android, there are two paths:

LocationManager

Pros

  • More granular control
  • Available in all devices
  • Part of the Android framework

Cons

  • Battery drain is an issue, if not managed properly
  • Requires logic to switch location providers, if the device is unable to find a location (ex. poor GPS inside a building)

Features

  • NMEA Listener
  • GPS Status Listener
  • Listen to provider status changes (ex. GPS is turned off by user)
  • List of providers to choose location source from

Providers

GPS

  • Permissions Required:
  • Accuracy: 10m - 100m
  • Power Requirements: HIGH
  • Availability: Worldwide (with clear view of the sky)
  • NOTES:
    • Location updates typically come in once every second, but in situations where GPS has not been used for some time and A-GPS is unavailable, it make take several minutes for a location to be received.
    • In cases where clear view of the sky is obstructed, GPS points will not cluster very well (location points "jump") and accuracy may be misleading in certain areas due to the "Urban Canyon" effect.

Network

  • Permissions Required:
  • Accuracy: 100m - 1000m+
  • Power Requirements: LOW - MEDIUM
  • Availability: Within range of cell tower or wifi signal
  • NOTES:
    • Location updates occur less frequently than GPS
    • Location updates typically do not cluster well (location points "jump") and accuracy can range depending number of different factors (number of wifi signals, signal strength, type of cell tower, etc.)

Passive

  • Permissions Required:
  • Accuracy: 10m - 1000m+
  • Power Requirements: NONE
  • Availability: Only when another app receives a location from either GPS or Network
  • NOTES:
    • Don't rely on this to give you continuous updates. This listens passively to other apps that make location requests, and passes those locations back.
    • Does not return FusedLocationProviderApi generated points, only the underlying location points used to generate them.

FusedLocationProviderApi

Pros

  • Offers less battery drain "out of the box"
  • Handles poor GPS well
  • Gets updates more regularly

Cons

  • Less granular control over GPS
  • May not be available on all devices or in certain countries
  • Requires third party library dependency

Features

  • Well managed use of location providers for optimal batter savings
  • Typically generates more accurate points then Network Location Provider
  • More frequent updates of library, allowing for more improvement
  • No need to specify what type of provider to use

LocationRequest Priority Levels

PRIORITY_HIGH_ACCURACY

  • Permissions Required:
  • Accuracy: 10m - 100m
  • Power Requirements: HIGH
  • Availability: Wherever Google Play Services is available.
  • NOTES:
    • If ACCESS_FINE_LOCATION is not used, this will not use GPS for generating location updates, but will still find a fairly accurate point in the right conditions.
    • If ACCESS_FINE_LOCATION is used, it may or may not use GPS to generate location points, depending on how accurate it can currently track the device given the environmental conditions.
    • Although this may report more accurate location updates than the other settings, it is still prone to the "Urban Canyon" effect.

PRIORITY_BALANCED_POWER_ACCURACY

  • Permissions Required:
  • Accuracy: 100m - 1000m+
  • Power Requirements: MEDIUM
  • Availability: Wherever Google Play Services is available.
  • NOTES:
    • Same notes as PRIORITY_HIGH_ACCURACY
    • Although it is unlikely, this setting may still use GPS to generate a location.

PRIORITY_LOW_POWER

  • Permissions Required:
  • Accuracy: 100m - 1000m+
  • Power Requirements: LOW
  • Availability: Wherever Google Play Services is available.
  • NOTES:
    • Probably does not use GPS, but untested thus far.
    • Updates are typically not very accurate
    • Used generally to detect significant changes in location

PRIORITY_NO_POWER

  • Permissions Required:
  • Accuracy: 10m - 1000m+
  • Power Requirements: NONE
  • Availability: Wherever Google Play Services is available.
  • NOTES:
    • Functions almost identically to LocationManager PASSIVE_PROVIDER
    • Reports back Google Play Services updates when received, where PASSIVE_PROVIDER reports back underlying location updates used

TroubleShooting

OnLocationChanged() Never Called

Since this seems to be a common issue with getting Android Locations, I'll put down a quick checklist of common fixes:


  1. Check your manifest!

    One of the most common issues is that the right permissions were never given. If you are using GPS (with or without Network), use <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>, else use <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>. Google's FusedLocationApi requires ACCESS_FINE_LOCATION.


  1. (For Android 6+) Check runtime permissions!

    Check for and request permissions! If you are never given permissions, you'll end up with crashes, or worse (if you are catching all exceptions), you'll end up with no indication of anything! It doesn't matter if the user grants you permission at the start of the app, always check to see if you have permissions for all calls. The user can easily go to their settings and revoke them.


  1. Double check your code!

    Are you sure you are passing in the right listener? Did you add that BroadcastReceiver or IntentService to your manifest? Are you using PendingIntent.getService() on a BroadcastReceiver class, or getBroadcast() on an IntentService class? Are you sure you are not unregistering your listener somewhere else in your code immediately after requesting?


  1. Check device settings!

    Obviously, make sure you have location services turned on.

    enter image description here

    If you are using Network services, did you turn on "Scanning Always Available"? Do you have your location mode set to "Best" ("High Accuracy") or "Battery Saving" ("Network Only")?

    enter image description here

    If you are using GPS, did you turn on "Best" ("High Accuracy") or "Device only" in location mode?

    enter image description here


  1. Double check your code!

    Yes, this is on here twice. Did you try using a LocationListener instead of a PendingIntent, or vice-versa, to ensure you actually implemented LocationManager properly? Are you sure that the location request isn't being removed in some part of the Activity or Service lifecycle that you didn't expect to happen?


  1. Check your surroundings!

    Are you testing GPS on the first floor of a building in the middle of San Francisco? Are you testing Network locations in the middle of nowhere? Do you work in a secret underground bunker void of all radio signals, wondering why your device isn't getting location? Always double check your surroundings when trying to troubleshoot location problems!


There could be many other less obvious reasons why location isn't working, but before searching out those esoteric fixes, just run through this quick checklist.

Related Examples