Geofencing in Android, A Simple Example.

By | February 12, 2017

What is Geofencing?

Geo-fencing is a feature in a software program that uses the global positioning system (GPS) or radio frequency identification (RFID) to define geographical boundaries. A geofence is a virtual barrier.

Today we will discuss how we can implement Geofencing in Android with a single location.

First You need to provide the permissions in the AndroidManifest.

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

Geofencing needs Google Services API.
Open your build.gradle and add the dependency.


    compile 'com.google.android.gms:play-services-location:8.4.0'

Here we are going to set a Fence of radius around our current location or the Last Known location in our Device.

Implement Geofencing.

First we have to check whether this device has Google Play Services Installed.

int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resp == ConnectionResult.SUCCESS) {
	mGoogleApiClient = new GoogleApiClient.Builder(this)
			.addApi(LocationServices.API)
			.addConnectionCallbacks(connectionAddListener)
			.addOnConnectionFailedListener(connectionFailedListener)
			.build();
	mGoogleApiClient.connect();
} else {
	Log.e(TAG, "Your Device doesn't support Google Play Services.");
}

For getting the last known location, we could use GoogleServices API itself.


	// Create the LocationRequest object
	mLocationRequest = LocationRequest.create()
		.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
		.setInterval(10 * 1000)        // 10 seconds, in milliseconds
		.setFastestInterval(1 * 1000); // 1 second, in milliseconds

Now implement “LocationListener” of GoogleServices API with the below methods.

Get the Location


Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

if (location == null) {

	LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,    mLocationRequest, this);

} else {

	currentLatitude = location.getLatitude();
	currentLongitude = location.getLongitude();

}

Location Listeners


@Override
public void onLocationChanged(Location location) {

	currentLatitude = location.getLatitude();
	currentLongitude = location.getLongitude();

}

Now we will add both Success and Fail Listeners.


private GoogleApiClient.ConnectionCallbacks connectionAddListener =
	new GoogleApiClient.ConnectionCallbacks() {
		@Override
		public void onConnected(Bundle bundle) {
		}

		@Override
		public void onConnectionSuspended(int i) {
		}
};

private GoogleApiClient.OnConnectionFailedListener connectionFailedListener =
	new GoogleApiClient.OnConnectionFailedListener() {
		@Override
		public void onConnectionFailed(ConnectionResult connectionResult) {

		}
};
            

Adding Geofencing


/**
 * Create a Geofence list by adding all fences you want to track
 */
public void createGeofences(double latitude, double longitude) {

	String id = UUID.randomUUID().toString();
	Geofence fence = new Geofence.Builder()
			.setRequestId(id)
			.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
			.setCircularRegion(latitude, longitude, 200) // Try changing your radius
			.setExpirationDuration(Geofence.NEVER_EXPIRE)
			.build();
	mGeofenceList.add(fence);

}

Create Geofencing Request and trigger


private GeofencingRequest getGeofencingRequest() {

	GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
	builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
	builder.addGeofences(mGeofenceList);
	return builder.build();

}

But wait…we need a class to Listen to…right…
So we will create an Intent Service and add the Pending Intent to it.

Add PendingIntent


private PendingIntent getGeofencePendingIntent() {

	// Reuse the PendingIntent if we already have it.
	if (mGeofencePendingIntent != null) {
		return mGeofencePendingIntent;
	}
	Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
	// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
	// calling addGeofences() and removeGeofences().
	return PendingIntent.getService(this, 0, intent, PendingIntent.
			FLAG_UPDATE_CURRENT);

}

Create a class “GeofenceTransitionsIntentService” that extends IntentService.

GeofenceTransitionsIntentService.java


package com.coderzheaven.geofencedemo;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingEvent;

public class GeofenceTransitionsIntentService extends IntentService {

    private static final String TAG = "GeofenceTransitions";

    public GeofenceTransitionsIntentService() {
        super("GeofenceTransitionsIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if (geofencingEvent.hasError()) {
            Log.e(TAG, "Goefencing Error " + geofencingEvent.getErrorCode());
            return;
        }

        // Get the transition type.
        int geofenceTransition = geofencingEvent.getGeofenceTransition();
        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER){
            showNotification("Entered", "Entered the Location");
        }
        else if(geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
            showNotification("Exited", "Exited the Location");
        } else {
            showNotification("Error", "Error");
    }

    public void showNotification(String text, String bigText) {

        // 1. Create a NotificationManager
        NotificationManager notificationManager =
                (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);

        // 2. Create a PendingIntent for AllGeofencesActivity
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

          // 3. Create and send a notification
        Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(text)
                .setContentText(text)
                .setContentIntent(pendingNotificationIntent)
                .setStyle(new NotificationCompat.BigTextStyle().bigText(bigText))
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setAutoCancel(true)
                .build();
        notificationManager.notify(0, notification);
    }
}

Download the Complete Android Studio Source Code from here.