Thanks to smartphones, modern mobile applications can benefit from GPS installed to get user current location. This information adds a lot of value to an application. Web’s giants have understood this since long time.

So, in your next application, you could use GPS or Network to get user current location and add value to your application. For example, if you create a weather application it is essential to know user location to access local weather associated.

To achieve that, there are 2 solutions in Android :

  1. User SDK standard solution
  2. Use Location APIs from Google Play Services

In this tutorial, we’re going to learn how to get user location by using SDK standard solution. It can be a better solution because some smartphones haven’t Google Play Services installed. So, combine both solutions can also be a good approach for your application.

First, you need to update your Android Manifest and add ACCESS_FINE_LOCATION permission like this :


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

In Android standard SDK, you have several providers that can provider you user’s location. Best is obviously GPS but you can get location informations from Network. To be sure to get user’s location, we’re trying to get user location from these both providers. So, you need to add INTERNET permission to your Android Manifest :


<uses-permission android:name="android.permission.INTERNET" />

Now, you can create location getter class. First, you need to get LocationManager service that is a system service. Instance of LocationManager lets you to check if a particular provider is enabled or no thanks to isProviderEnabled method with provider type in parameter.

If GPS and Network providers are disabled, we stop and return false to indicate to caller that there are no providers enabled on user’s device. Otherwise, we request location updates thanks to method requestLocationUpdates. This method takes a LocationListener instance that will be called when there is an event : location changed, provider disabled, provider enabled or status changed.

To limit user’s location search, we use a GetLastLocation task delayed in 20 seconds. In that task, we stop user’s location search and try to get last known location if there is no result before during request. If there are both results : one from GPS and one from Network, we take the last one.

To let user get user’s location when it’s available, we use a LocationResult abstract class with a gotLocation method that is called when location is found or search is ended.

Our LocationGetter class is like that :


import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class LocationGetter {
 private Timer timer;
 private LocationManager locationManager;
 private LocationResult locationResult;
 private boolean gpsEnabled = false;
 private boolean networkEnabled = false;

 public boolean getLocation(Context context, LocationResult result) {
   locationResult = result;

   if (locationManager == null) {
     locationManager = (LocationManager) context
        .getSystemService(Context.LOCATION_SERVICE);
   }

   try {
     gpsEnabled = locationManager
       .isProviderEnabled(LocationManager.GPS_PROVIDER);
   } catch (Exception ex) {
   }

   try {
     networkEnabled = locationManager
       .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
   } catch (Exception ex) {
   }

   // stop if no providers are enabled
   if (!gpsEnabled && !networkEnabled) {
     return false;
   }

   if (gpsEnabled) {
     locationManager.requestLocationUpdates(
       LocationManager.GPS_PROVIDER, 0, 0,locationListenerGps);
   }

   if (networkEnabled) {
     locationManager.requestLocationUpdates(
       LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
   }

   timer = new Timer();
   timer.schedule(new GetLastLocation(), 20000);

   return true;
 }

 LocationListener locationListenerGps = new LocationListener() {
   public void onLocationChanged(Location location) {
     timer.cancel();
     locationResult.gotLocation(location);
     locationManager.removeUpdates(this);
     locationManager.removeUpdates(locationListenerNetwork);
   }

   public void onProviderDisabled(String provider) {
   }

   public void onProviderEnabled(String provider) {
   }

   public void onStatusChanged(String provider, int status, Bundle extras) {
   }
 };

 LocationListener locationListenerNetwork = new LocationListener() {
   public void onLocationChanged(Location location) {
     timer.cancel();
     locationResult.gotLocation(location);
     locationManager.removeUpdates(this);
     locationManager.removeUpdates(locationListenerGps);
   }

   public void onProviderDisabled(String provider) {
   }

   public void onProviderEnabled(String provider) {
   }

   public void onStatusChanged(String provider, int status, Bundle extras) {
   }
 };

 class GetLastLocation extends TimerTask {
   @Override
   public void run() {
     locationManager.removeUpdates(locationListenerGps);
     locationManager.removeUpdates(locationListenerNetwork);

     Location netLocation = null, gpsLocation = null;

     if (gpsEnabled)
       gpsLocation = locationManager
         .getLastKnownLocation(LocationManager.GPS_PROVIDER);

     if (networkEnabled)
       netLocation = locationManager
         .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

     // if there are both values use the latest one
     if (gpsLocation != null && netLocation != null) {
       if (gpsLocation.getTime() > netLocation.getTime())
         locationResult.gotLocation(gpsLocation);
       else
         locationResult.gotLocation(netLocation);

       return;
     }

     if (gpsLocation != null) {
       locationResult.gotLocation(gpsLocation);
       return;
     }

     if (netLocation != null) {
       locationResult.gotLocation(netLocation);
       return;
     }

     locationResult.gotLocation(null);
   }
 }

 // Represents a Location Result
 public static abstract class LocationResult {
   public abstract void gotLocation(Location location);
 }
}

Now, you must call your LocationGetter instance from an activity like that :


LocationGetter userLocation = new LocationGetter();
boolean locationEnabled = userLocation.getLocation(this, locationResult);

if (!locationEnabled) {
  // message to user to indicate to enable location on his device ...
}