How to Work With Geolocation on Android

That is a common practice when a developer needs to get the device’s coordinates. Fortunately, all modern smartphones, regardless of the platform they run on, have built-in tools for this purpose.
In this article, we will talk about dealing with geolocations in the Android OS. Let’s first of all point out the main methods of location tracking.
GPS
Nowadays, this method allows us to track location with the highest possible accuracy. Some drawbacks it has are as follows: high energy consumption, impossibility to track location indoors, troubles finding satellites.
Wi-Fi Networks
This method allows getting coordinates of the device quite fast. It uses the Wi-Fi network's databases for this purpose. The need to use this method arises mostly indoors. Tracking location with the help of Wi-Fi networks doesn’t influence energy consumption. The main drawback is that Wi-Fi networks are not available everywhere.
Mobile Networks
They are much more widespread than Wi-Fi networks. But the return coordinates have significantly lower accuracy than the previous method. This is due to the fact that the distance to the nearest cell tower can sometimes reach tens of kilometers.
Android OS offers several methods of current location tracking. Before starting, one has to add the permission to AndroidManifest to access the geolocation.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
This permission allows us to work with both GPS and network coordinate providers. When we only need the ability to work with network providers, we can use ACCESSCOARSELOCATION.
- LocationManager. It allows us to control the work with geopositions, setting such parameters as the used provider type (GPS, networks), accuracy, speed, frequency etc. To get the instance of this class, you need to call
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); |
To sign up for the notifications about the changes in location, we need to define LocationListener and send it as a parameter to the requestLocationUpdates method:
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); | |
LocationListener locationListener = new LocationListener() { | |
public void onLocationChanged(Location location) { | |
// Called when a new location is found by the network location provider. | |
doSomethingWithLocation(location); | |
} | |
public void onStatusChanged(String provider, int status, Bundle extras) {} | |
public void onProviderEnabled(String provider) {} | |
public void onProviderDisabled(String provider) {} | |
}; | |
// Register the listener with the Location Manager to receive location updates | |
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); |
In this example, LocationManager is subscribed to get notifications about the location changes only from the Wi-Fi networks and cell towers (but we can as well request GPS usage). The second parameter of the requestLocationUpdates method is intended to control the update timeframe, the third one - to control the distance. The fourth parameter is a callback, getting notifications. In this case, the notifications will be received as often as possible. But it is recommended to expand the second and the third parameter within the allowed measurement accuracy to save the battery charge.
The method described above allows us to get the coordinates both immediately and within a few minutes. This can be unacceptable when we need to track the user’s location very fast. That is why we can get the last coordinates the system knows. This can be done in the following way:
String locationProvider = LocationManager.NETWORK_PROVIDER; | |
// Or LocationManager.GPS_PROVIDER | |
Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider); |
Judging from our own experience when using this method, we can say that sometimes really old (and outdated) information about the coordinates or even null can be returned. It can occur if geolocation on the user’s device has been off for some time or if it hasn’t been enabled at all.
- Google Play Services. The process of including this library is described here. It gives lots of opportunities, but it is impossible to list all of them in this article. Its main feature is that this library can track location by itself or on request of an app and allows to get the coordinates very fast.
In one of the last versions of the Google Play Services library LocationClient class is marked as deprecated. It is recommended to use GoogleApiClient instead of it. This class allows working with many Google services (not only geolocation). Now to get the coordinates, we need to make 2 other callbacks:
GoogleApiClient.ConnectionCallbacks, | |
GoogleApiClient.OnConnectionFailedListener |
After doing so we need to use GoogleApiClient object’s builder:
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(Context) | |
.addConnectionCallbacks(GoogleApiClient.ConnectionCallbacks) | |
.addOnConnectionFailedListener( | |
GoogleApiClient.OnConnectionFailedListener) | |
.addApi(LocationServices.API) | |
.build() |
In the onStart() method of Activity class we call GoogleApiClient.connect(). In onStop() method we call GoogleApiClient.disconnect() (to save the battery life), if GoogleApiClient.isConnected() returns true.
After the callback onConnected(Bundle bundle) is called, we can get the last coordinates - LocationServices.FusedLocationApi.getLastLocation(GoogleApiClient). From our own experience, we can tell that usually, the most up-to-date coordinates are the ones that are returned. In the case null returns (which happens quite rarely), we can request the coordinates update with the help of LocationServices.FusedLocationApi.requestLocationUpdates method. We have to pass the LocationRequest object (it allows to set up update parameters, such as frequency of updates, accuracy etc.) and LocationListener to it. As soon as we get the coordinates (it usually takes 1-2 seconds) the callback onLocationChanged(Location location) will be called.
public class LocationActivity extends FragmentActivity implements | |
GoogleApiClient.ConnectionCallbacks, | |
GoogleApiClient.OnConnectionFailedListener, | |
LocationListener{ | |
private LocationRequest mLocationRequest; | |
private GoogleApiClient mGoogleApiClient; | |
@Override | |
protected void onCreate(Bundle arg0) { | |
super.onCreate(arg0); | |
mLocationRequest = LocationRequest.create(); | |
/* | |
* Set the update interval | |
*/ | |
mLocationRequest.setInterval(300000); | |
// Use high accuracy | |
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); | |
// Set the interval ceiling to one minute | |
mLocationRequest.setFastestInterval(180000); | |
mGoogleApiClient = new GoogleApiClient.Builder(Context) | |
.addConnectionCallbacks(GoogleApiClient.ConnectionCallbacks) | |
.addOnConnectionFailedListener( | |
GoogleApiClient.OnConnectionFailedListener) | |
.addApi(LocationServices.API) | |
.build(); | |
} | |
@Override | |
protected void onStart() { | |
super.onStart(); | |
mGoogleApiClient.connect(); | |
} | |
@Override | |
protected void onStop() { | |
super.onStop(); | |
if (mGoogleApiClient.isConnected()) { | |
mGoogleApiClient.disconnect(); | |
} | |
} | |
@Override | |
public void onConnectionFailed(ConnectionResult arg0) { | |
// Handle this according to the logic of your app | |
} | |
@Override | |
public void onConnected(Bundle arg0) { | |
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); | |
if (lastLocation == null) { | |
LocationServices.FusedLocationApi.requestLocationUpdates( | |
mGoogleApiClient, mLocationRequest, this); | |
} | |
} | |
@Override | |
public void onDisconnected() {} | |
@Override | |
public void onLocationChanged(Location location) { | |
// doSomethingWithNewLocation(location); | |
} | |
} |
Provider Availability Check
Before trying to get the coordinates, we have to check if the geolocation is on and if there are any available providers. We offer the following method of doing this. The main idea is not to have to call LocationManager (its behavior has changed in Android version 4.3) directly but to use the access capability of the system parameters.
The tasks with geolocation occur quite often. In this regard, Android OS has a number of quite convenient tools we can use when working with coordinates. We recommend using Google Play Services instead of working with LocationManager directly. Trust us, it can save you a lot of efforts! Moreover, this library is preinstalled on all devices running on Android 2.2 and later and Google is actively developing and distributing it.
Want to learn more about our Android development services?
Get in touch with us to discuss your Android project and learn how our team can assist you.