Android Location Services
Location awareness is an important feature in most Android Applications. Recently I had to get the current location’s latitude and longitude values to list down the places near by. I tried 2 ways to achieve this, one provided by Android platform and other by Google Play Services. Here I am going to explain and compare those 2 in detail.
- Android framework Location API
- FusedLocationProviderClient by Google Play Services
Android Framework Location API
This approach makes use of Location Services provided by android.location package. These services are provided by Android platform by default. Using these app can access system’s location services and get periodic updates of device’s geographical location.
Set up Permissions
First we need to request user permissions to access location by declaring as follows in AndroidManifest.xml file.
- ACCESS_FINE_LOCATION includes permission for both GPS_PROVIDER and NETWORK _PROVIDER.
- ACCESS_COARSE_LOCATION includes permissions only for NETWORK_PROVIDER.
(If you do not add these permissions your app will fail at run time.)
Implementation
Let me walk through the details of the implementation. First section is implementing the LocationListener.
LocationListener class needs to override 4 methods as shown above. Out of them following two are more useful.
- onLocationChanged method will be notified when it receives a new location update. We can use it to send location updates to UI.
- onProviderDisabled method is notified when the gps is turned off. So we can create an intent for taking user to the settings panel to enable gps.
To access location we need a Location Manager instance. Next we are going to create an instance of LocationManager. Since this is a System Service we need to call getSystemService function by passing the type of service requesting as LOCATION_SERVICE.
mLocationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
As you see, I have implemented a permission check next. This is because from API level 23 and above it is required to check user permissions at run time to enable services even though we have already added them in Manifest file.
(You may notice a warning asking to explicitly check user permission for requestLocationUpdates function which we are going to talk about later.)
We will request permissions using requestPermissions function including all the 3 permissions we previously added in manifest file. The last argument is request code which is an integer value used to track the request in the onRequestPermissionResults method which handles permission results.
Then we can call requestLocationUpdates method of LocationManager to get location updates.
mLocationManager.requestLocationUpdates(provider, 1000, 0f, mLocationListener)
There are 4 parameters we need to pass into this function.
First parameter is Provider, It can be either “GPS”, “NETWORK” or “PASSIVE” provider.
- GPS provider : determines location using Satellites. It may take a while to return a location fix.
- NETWORK provider : determines location based on availability of cell tower and wifi access points.
- PASSIVE provider : does not call for location updates by itself instead it uses location results generated by other providers when other applications request them.
Second parameter is Min time in milliseconds that location should be refreshed. According to our example location is refreshed in every 1 second.
Third parameter is Min distance that device has to move by initial location to receive a location update. Let’s say we add 500f here, then new location update will be available when user moves 500m from his current location. In our example we have set it to 0f. That means we will receive location updates even if user stays still in his current location.
Fourth parameter is Listener instance.
Instead of manually specifying the provider as “GPS” or “Network”, I have used getBestProvider method to determine the best provider at run time based on the given criteria.
OK that is the end of implementation of Android Framework Location API. To refer the source code click here.
Let’s move on to implementation of FusedLocationProviderClient by Google Play Services.
FusedLocationProviderClient by Google Play Services
Before discussing this topic, let’s first have a quick peek at Google Location Services API.
Google Location Services API is a part of Goole Play Services and it is built on top of Android’s APIs. It provides powerful high-level framework by automating location provider choice and power management. It uses FusedLocationProviderApi to automatically choose which underlying provider to use based on accuracy, battery usage and etc.
But from Google Play Service version 11.6.0, it has been deprecated and recommends us to use FusedLocationProviderClient instead. FusedLocationProviderClient acts as a common entry point to all Google’s location services.
Include Google Play Services in the project
As mentioned above this location service is a part of Google Play Services. So we need to add the following dependancy in build.gradle.
implementation "com.google.android.gms:play-services:11.6.0"
Set up Permission
Set up user permissions in AndroidManifest file.
Implementation
First thing to do is create an instance of FusedLocationProviderClient inside onCreate method.This will take care of all connection logic on its own.
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
(We will discuss about locationRequest and locationCallback later.)
Implement check for run time user permissions for devices with API level 23 and higher as we did in earlier example.
and get permission results on onRequestPermissionResult method.
Finally request location updates.
As you see, we are trying to get the location using lastLocation. If we already have results for lastLocation that is the end of the story. But this last location can be null due to following reasons.
- GPS is turned off in the device settings.
- The device never recorded its location due to the case of device being new or been restored to factory settings.
- Google Play Services on the device has been restarted and no active Fused Location Provider Client has requested location after that.
In that case we can “request for location updates”. The “else” part of the above code represents the location update request. This will give us continuous location updates at specific time intervals. For that we have to pass locationRequest and locationCallback parameters.
mFusedLocationClient?.requestLocationUpdates(locationRequest, locationCallback, null)
Let’s talk about locationRequest. As name implies it is a request for location.
- Priority helps to determine which location sources to use. eg: PRIORITY_HIGH_ACCURACY is more likely to use GPS and PRIORITY_BALANCED_POWER_ACCURACY is more likely to use cell tower and wifi.
- Interval helps to obtain location updates at this specific time interval.
- FastestInterval helps to explicitly set fastest rate that our app receives location updates.
locationCallback will receive location request results. Inside this we can assign location result to the variable. Once we get a location fix we can remove continuous location updates as shown below.
Ok this is the end of FusedLocationProviderClient implementation. Click here to refer the source code.
Conclusion
Both these approaches are fine to follow when receiving location results. But Android official documentation strongly suggests to use Google Location Services over Android framework location APIs. Because it automates location provider choice and power management.
Google Location Services provides significant benefits when compared to Android Framework Location API. It gives faster results because results are fetched from system wide-service that keeps updating it. Stability during usage and less battery consumption are also noticed. We can also use advanced features such as Geofencing.
The only disadvantage is, Google Location Services requires “Google Play Services” to be installed on the device to use location service. If it is not an option we can still go with Android Framework Location API.