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.

Fused location API

Example Using Activity with LocationRequest

/* * This example is useful if you only want to receive updates in this * activity only, and have no use for location anywhere else. */public class LocationActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,LocationListener { private GoogleApiClient mGoogleApiClient; private LocationRequest mLocationRequest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build(); mLocationRequest = new LocationRequest() .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)//GPS quality location points .setInterval(2000) //At least once every 2 seconds .setFastestInterval(1000); //At most once a second } @Override protected void onStart(){ super.onStart(); mGoogleApiClient.connect(); } @Override protected void onResume(){ super.onResume(); //Permission check for Android 6.0+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if(mGoogleApiClient.isConnected()) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } } } @Override protected void onPause(){ super.onPause(); //Permission check for Android 6.0+ if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if(mGoogleApiClient.isConnected()) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); } } } @Override protected void onStop(){ super.onStop(); mGoogleApiClient.disconnect(); } @Override public void onConnected(@Nullable Bundle bundle) { if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } } @Override public void onConnectionSuspended(int i) { mGoogleApiClient.connect(); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } @Override public void onLocationChanged(Location location) { //Handle your location update code here } }
Code language: JavaScript (javascript)

Example Using Service with PendingIntent and BroadcastReceiver.

ExampleActivity

Recommended reading: LocalBroadcastManager

/* * This example is useful if you have many different classes that should be * receiving location updates, but want more granular control over which ones * listen to the updates. * * For example, this activity will stop getting updates when it is not visible, but a database * class with a registered local receiver will continue to receive updates, until "stopUpdates()" is called here. * */ public class ExampleActivity extends AppCompatActivity { private InternalLocationReceiver mInternalLocationReceiver; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); //Create internal receiver object in this method only. mInternalLocationReceiver = new InternalLocationReceiver(this); } @Override protected void onResume(){ super.onResume(); //Register to receive updates in activity only when activity is visible LocalBroadcastManager.getInstance(this).registerReceiver(mInternalLocationReceiver, new IntentFilter("googleLocation")); } @Override protected void onPause(){ super.onPause(); //Unregister to stop receiving updates in activity when it is not visible. //NOTE: You will still receive updates even if this activity is killed. LocalBroadcastManager.getInstance(this).unregisterReceiver(mInternalLocationReceiver); } //Helper method to get updates private void requestUpdates(){ startService(new Intent(this, LocationService.class).putExtra("request", true)); } //Helper method to stop updates private void stopUpdates(){ startService(new Intent(this, LocationService.class).putExtra("remove", true)); } /* * Internal receiver used to get location updates for this activity. * * This receiver and any receiver registered with LocalBroadcastManager does * not need to be registered in the Manifest. * */ private static class InternalLocationReceiver extends BroadcastReceiver{ private ExampleActivity mActivity; InternalLocationReceiver(ExampleActivity activity){ mActivity = activity; } @Override public void onReceive(Context context, Intent intent) { final ExampleActivity activity = mActivity; if(activity != null) { LocationResult result = intent.getParcelableExtra("result"); //Handle location update here } } } }
Code language: JavaScript (javascript)

LocationService

NOTE: Don’t forget to register this service in the Manifest!

public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { private GoogleApiClient mGoogleApiClient; private LocationRequest mLocationRequest; @Override public void onCreate(){ super.onCreate(); mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApi(LocationServices.API).build(); mLocationRequest = new LocationRequest() .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) //GPS quality location points .setInterval(2000) //At least once every 2 seconds .setFastestInterval(1000); //At most once a second } @Override public int onStartCommand(Intent intent, int flags, int startId){ super.onStartCommand(intent, flags, startId); //Permission check for Android 6.0+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (intent.getBooleanExtra("request", false)) { if (mGoogleApiClient.isConnected()) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, getPendingIntent()); } else { mGoogleApiClient.connect(); } } else if(intent.getBooleanExtra("remove", false)) { stopSelf(); } } return START_STICKY; } @Override public void onDestroy(){ super.onDestroy(); if(mGoogleApiClient.isConnected()){ LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, getPendingIntent()); mGoogleApiClient.disconnect(); } } private PendingIntent getPendingIntent(){ //Example for IntentService //return PendingIntent.getService(this, 0, new Intent(this, **YOUR_INTENT_SERVICE_CLASS_HERE**), PendingIntent.FLAG_UPDATE_CURRENT); //Example for BroadcastReceiver return PendingIntent.getBroadcast(this, 0, new Intent(this, LocationReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT); } @Override public void onConnected(@Nullable Bundle bundle) { //Permission check for Android 6.0+ if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, getPendingIntent()); } } @Override public void onConnectionSuspended(int i) { mGoogleApiClient.connect(); } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {} @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
Code language: JavaScript (javascript)

LocationReceiver

NOTE: Don’t forget to register this receiver in the Manifest!

public class LocationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if(LocationResult.hasResult(intent)){ LocationResult locationResult = LocationResult.extractResult(intent); LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("googleLocation").putExtra("result", locationResult)); } } }
Code language: PHP (php)

Get Address From Location using Geocoder

After you got the Location object from FusedAPI, you can easily acquire Address information from that object.

private Address getCountryInfo(Location location) { Address address = null; Geocoder geocoder = new Geocoder(getActivity(), Locale.getDefault()); String errorMessage; List<Address> addresses = null; try { addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), // In this sample, get just a single address. 1); } catch (IOException ioException) { // Catch network or other I/O problems. errorMessage = "IOException>>" + ioException.getMessage(); } catch (IllegalArgumentException illegalArgumentException) { // Catch invalid latitude or longitude values. errorMessage = "IllegalArgumentException>>" + illegalArgumentException.getMessage(); } if (addresses != null && !addresses.isEmpty()) { address = addresses.get(0); } return country; }
Code language: PHP (php)

Requesting location updates using LocationManager

As always, you need to make sure you have the required permissions.

public class MainActivity extends AppCompatActivity implements LocationListener{ private LocationManager mLocationManager = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); } @Override protected void onResume() { super.onResume(); try { mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); } catch(SecurityException e) { // The app doesn't have the correct permissions } } @Override protected void onPause() { try{ mLocationManager.removeUpdates(this); } catch (SecurityException e){ // The app doesn't have the correct permissions } super.onPause(); } @Override public void onLocationChanged(Location location) { // We received a location update! Log.i("onLocationChanged", location.toString()); } @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(String provider) {} @Override public void onProviderDisabled(String provider) {} }
Code language: JavaScript (javascript)

Requesting location updates on a separate thread using LocationManager

As always, you need to make sure you have the required permissions.

public class MainActivity extends AppCompatActivity implements LocationListener{ private LocationManager mLocationManager = null; HandlerThread mLocationHandlerThread = null; Looper mLocationHandlerLooper = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); mLocationHandlerThread = new HandlerThread("locationHandlerThread"); } @Override protected void onResume() { super.onResume(); mLocationHandlerThread.start(); mLocationHandlerLooper = mLocationHandlerThread.getLooper(); try { mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this, mLocationHandlerLooper); } catch(SecurityException e){ // The app doesn't have the correct permissions } } @Override protected void onPause() { try{ mLocationManager.removeUpdates(this); } catch (SecurityException e){ // The app doesn't have the correct permissions } mLocationHandlerLooper = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) mLocationHandlerThread.quitSafely(); else mLocationHandlerThread.quit(); mLocationHandlerThread = null; super.onPause(); } @Override public void onLocationChanged(Location location) { // We received a location update on a separate thread! Log.i("onLocationChanged", location.toString()); // You can verify which thread you're on by something like this: // Log.d("Which thread?", Thread.currentThread() == Looper.getMainLooper().getThread() ? "UIThread" : "New thread"); } @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(String provider) {} @Override public void onProviderDisabled(String provider) {} }
Code language: JavaScript (javascript)

Getting location updates in a BroadcastReceiver

First, create a BroadcastReceiver class to handle the incoming Location updates:

public class LocationReceiver extends BroadcastReceiver implements Constants { @Override public void onReceive(Context context, Intent intent) { if (LocationResult.hasResult(intent)) { LocationResult locationResult = LocationResult.extractResult(intent); Location location = locationResult.getLastLocation(); if (location != null) { // Do something with your location } else { Log.d(LocationReceiver.class.getSimpleName(), "*** location object is null ***"); } } } }
Code language: JavaScript (javascript)

Then when you connect to the GoogleApiClient in the onConnected callback:

@Override public void onConnected(Bundle connectionHint) { Intent backgroundIntent = new Intent(this, LocationReceiver.class); mBackgroundPendingIntent = backgroundPendingIntent.getBroadcast(getApplicationContext(), LOCATION_REUEST_CODE, backgroundIntent, PendingIntent.FLAG_CANCEL_CURRENT); mFusedLocationProviderApi.requestLocationUpdates(mLocationClient, mLocationRequest, backgroundPendingIntent); }
Code language: JavaScript (javascript)

Don’t forget to remove the location update intent in the appropriate lifecycle callback:

@Override public void onDestroy() { if (servicesAvailable && mLocationClient != null) { if (mLocationClient.isConnected()) { fusedLocationProviderApi.removeLocationUpdates(mLocationClient, backgroundPendingIntent); // Destroy the current location client mLocationClient = null; } else { mLocationClient.unregisterConnectionCallbacks(this); mLocationClient = null; } } super.onDestroy(); }
Code language: JavaScript (javascript)

Register geofence

I have created GeoFenceObserversationService singleton class.

GeoFenceObserversationService.java:

public class GeoFenceObserversationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> { protected static final String TAG = "GeoFenceObserversationService"; protected GoogleApiClient mGoogleApiClient; protected ArrayList<Geofence> mGeofenceList; private boolean mGeofencesAdded; private SharedPreferences mSharedPreferences; private static GeoFenceObserversationService mInstant; public static GeoFenceObserversationService getInstant(){ return mInstant; } @Override public void onCreate() { super.onCreate(); mInstant = this; mGeofenceList = new ArrayList<Geofence>(); mSharedPreferences = getSharedPreferences(AppConstants.SHARED_PREFERENCES_NAME, MODE_PRIVATE); mGeofencesAdded = mSharedPreferences.getBoolean(AppConstants.GEOFENCES_ADDED_KEY, false); buildGoogleApiClient(); } @Override public void onDestroy() { mGoogleApiClient.disconnect(); super.onDestroy(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } protected void buildGoogleApiClient() { mGoogleApiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this) .addApi(LocationServices.API) .build(); mGoogleApiClient.connect(); } @Override public void onConnected(Bundle connectionHint) { } @Override public void onConnectionFailed(ConnectionResult result) { } @Override public void onConnectionSuspended(int cause) {} private GeofencingRequest getGeofencingRequest() { GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); builder.addGeofences(mGeofenceList); return builder.build(); } public void addGeofences() { if (!mGoogleApiClient.isConnected()) { Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show(); return; } populateGeofenceList(); if(!mGeofenceList.isEmpty()){ try { LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, getGeofencingRequest(), getGeofencePendingIntent()).setResultCallback(this); } catch (SecurityException securityException) { securityException.printStackTrace(); } } } public void removeGeofences() { if (!mGoogleApiClient.isConnected()) { Toast.makeText(this, getString(R.string.not_connected), Toast.LENGTH_SHORT).show(); return; } try { LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient, getGeofencePendingIntent()).setResu ltCallback(this); } catch (SecurityException securityException) { securityException.printStackTrace(); } } public void onResult(Status status) { if (status.isSuccess()) { mGeofencesAdded = !mGeofencesAdded; SharedPreferences.Editor editor = mSharedPreferences.edit(); editor.putBoolean(AppConstants.GEOFENCES_ADDED_KEY, mGeofencesAdded); editor.apply(); } else { String errorMessage = AppConstants.getErrorString(this,status.getStatusCode()); Log.i("Geofence", errorMessage); } } private PendingIntent getGeofencePendingIntent() { Intent intent = new Intent(this, GeofenceTransitionsIntentService.class); return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); } private void populateGeofenceList() { mGeofenceList.clear(); List<GeoFencingResponce> geoFenceList = getGeofencesList; if(geoFenceList!=null&&!geoFenceList.isEmpty()){ for (GeoFencingResponce obj : geoFenceList){ mGeofenceList.add(obj.getGeofence()); Log.i(TAG,"Registered Geofences : " + obj.Id+"-"+obj.Name+"-"+obj.Lattitude+"- "+obj.Longitude); } } } }
Code language: HTML, XML (xml)

AppConstant:

public static final String SHARED_PREFERENCES_NAME = PACKAGE_NAME + ".SHARED_PREFERENCES_NAME"; public static final String GEOFENCES_ADDED_KEY = PACKAGE_NAME + ".GEOFENCES_ADDED_KEY"; public static final String DETECTED_GEOFENCES = "detected_geofences"; public static final String DETECTED_BEACONS = "detected_beacons"; public static String getErrorString(Context context, int errorCode) { Resources mResources = context.getResources(); switch (errorCode) { case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE: return mResources.getString(R.string.geofence_not_available); case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES: return mResources.getString(R.string.geofence_too_many_geofences); case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS: return mResources.getString(R.string.geofence_too_many_pending_intents); default: return mResources.getString(R.string.unknown_geofence_error); } }
Code language: PHP (php)

Where I started Service? From Application class

startService(new Intent(getApplicationContext(),GeoFenceObserversationService.class));
Code language: PHP (php)

How I registered Geofences?

GeoFenceObserversationService.getInstant().addGeofences();
Code language: CSS (css)

Leave a Reply

Your email address will not be published. Required fields are marked *