How to Create Geofence in an Android?

how to create geofence in google maps
android geofencing with google maps
draw geofence on google map android
geofencing app
geofencing android example androidhive
geofencing android example github
android geofencing without google maps
geofencing push notifications android

How to Create Geo fence(Creating and Monitoring Geo fences) on current latitude,longitude. I am trying multiple example but not create. Using this code:

public Geofence geofence(float radius, double latitude, double longitude) {
    String id = UUID.randomUUID().toString();
    return new Geofence.Builder()
            .setRequestId(id)
            .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
            .setCircularRegion(latitude, longitude, radius)
            .setExpirationDuration(Geofence.NEVER_EXPIRE)
            .build();
}

There's this tutorial from Google, that's very easy to follow:

http://io2015codelabs.appspot.com/codelabs/geofences

There's also a course at Udacity that teaches location services, including geofences:

https://www.udacity.com/course/google-location-services-on-android--ud876-1

Add Google Play Services to Gradle File:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.0.0'
    compile 'com.google.android.gms:play-services:7.3.0'
}

Add to Manifest File:

<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

Add to Activity's XML Layout file:

<Button
        android:id="@+id/add_geofences_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:onClick="addGeofencesButtonHandler"
        android:text="Add GeoFences" />

Add to Activity's Java File:

public class MainActivity extends Activity
implements
GoogleApiClient.ConnectionCallbacks, 
GoogleApiClient.OnConnectionFailedListener, 
ResultCallback<Status>{ 

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mAddGeofencesButton = (Button) findViewById(R.id.add_geofences_button);
        // Empty list for storing geofences.
        mGeofenceList = new ArrayList<Geofence>();

        // Get the geofences used. Geofence data is hard coded in this sample.
        populateGeofenceList();

        // Kick off the request to build GoogleApiClient.
        buildGoogleApiClient();
    }

protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

public void populateGeofenceList() {
for (Map.Entry<String, LatLng> entry : Constants.LANDMARKS.entrySet()) {
mGeofenceList.add(new Geofence.Builder()
   .setRequestId(entry.getKey())
   .setCircularRegion(
   entry.getValue().latitude,
   entry.getValue().longitude,
   Constants.GEOFENCE_RADIUS_IN_METERS
   )
   .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
   .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
   Geofence.GEOFENCE_TRANSITION_EXIT)
   .build());
   }
}

@Override
protected void onStart() {
    super.onStart();
    if (!mGoogleApiClient.isConnecting() || !mGoogleApiClient.isConnected()) {
        mGoogleApiClient.connect();
    }
}

@Override
protected void onStop() {
    super.onStop();
    if (mGoogleApiClient.isConnecting() || mGoogleApiClient.isConnected()) {
        mGoogleApiClient.disconnect();
    }
}

@Override
public void onConnected(Bundle connectionHint) {

}

@Override
public void onConnectionFailed(ConnectionResult result) {
    // Do something with result.getErrorCode());
}

@Override
public void onConnectionSuspended(int cause) {
    mGoogleApiClient.connect();
}

    public void addGeofencesButtonHandler(View view) {
            if (!mGoogleApiClient.isConnected()) {
                Toast.makeText(this, "Google API Client not connected!", Toast.LENGTH_SHORT).show();
                return;
            }

            try {
                LocationServices.GeofencingApi.addGeofences(
                        mGoogleApiClient,
                        getGeofencingRequest(),
                        getGeofencePendingIntent()
                ).setResultCallback(this); // Result processed in onResult().
            } catch (SecurityException securityException) {
                // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
            }
    }

   private GeofencingRequest getGeofencingRequest() {
        GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
        builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
        builder.addGeofences(mGeofenceList);
        return builder.build();
    }

    private PendingIntent getGeofencePendingIntent() {
            Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
            // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling addgeoFences()
            return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        }

public void onResult(Status status) {
        if (status.isSuccess()) {
            Toast.makeText(
                    this,
                    "Geofences Added",
                    Toast.LENGTH_SHORT
            ).show();
        } else {
            // Get the status code for the error and log it using a user-friendly message.
            String errorMessage = GeofenceErrorMessages.getErrorString(this,
                    status.getStatusCode());
        }
    }

Create a java file called Constans:

public class Constants {

    public static final long GEOFENCE_EXPIRATION_IN_MILLISECONDS = 12 * 60 * 60 * 1000;
    public static final float GEOFENCE_RADIUS_IN_METERS = 20;

    public static final HashMap<String, LatLng> LANDMARKS = new     HashMap<String, LatLng>();
    static {
        // San Francisco International Airport.
        LANDMARKS.put("Moscone South", new LatLng(37.783888,-122.4009012));

        // Googleplex.
        LANDMARKS.put("Japantown", new LatLng(37.785281,-122.4296384));

        // Test
        LANDMARKS.put("SFO", new LatLng(37.621313,-122.378955));
    }
}

Create a java file called GeofenceTransitionsIntentService:

public class GeofenceTransitionsIntentService extends IntentService {
  protected static final String TAG = "GeofenceTransitionsIS";

  public GeofenceTransitionsIntentService() {
    super(TAG);  // use TAG to name the IntentService worker thread
  }

  @Override
  protected void onHandleIntent(Intent intent) {
    GeofencingEvent event = GeofencingEvent.fromIntent(intent);
    if (event.hasError()) {
      Log.e(TAG, "GeofencingEvent Error: " + event.getErrorCode());
      return;
    }
  }

 String description = getGeofenceTransitionDetails(event);
   sendNotification(description);
 }

   private static String getGeofenceTransitionDetails(GeofencingEvent event) {
String transitionString =
    GeofenceStatusCodes.getStatusCodeString(event.getGeofenceTransition());
List triggeringIDs = new ArrayList();
for (Geofence geofence : event.getTriggeringGeofences()) {
  triggeringIDs.add(geofence.getRequestId());
}
return String.format("%s: %s", transitionString, TextUtils.join(", ", triggeringIDs));
}

  private void sendNotification(String notificationDetails) {
    // Create an explicit content Intent that starts MainActivity.
    Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);

    // Get a PendingIntent containing the entire back stack.
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
    stackBuilder.addParentStack(MainActivity.class).addNextIntent(notificationIntent);
    PendingIntent notificationPendingIntent =
        stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

    // Get a notification builder that's compatible with platform versions >= 4
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

    // Define the notification settings.
    builder.setColor(Color.RED)
        .setContentTitle(notificationDetails)
        .setContentText("Click notification to return to App")
        .setContentIntent(notificationPendingIntent)
        .setAutoCancel(true);

    // Fire and notify the built Notification.
    NotificationManager notificationManager =
        (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, builder.build());
  }

You should probably stick to their tutorial instead of copying and pasting the code to your project :D

Source

How to Work With Geofences on Android - Code Tuts, How to create a Geofence object. For this tutorial, we will use Java. Let's kick things off by creating a geofence. Firstly, create your geofencing� On Android, there are several ways to work with geofences. You could even create your own implementation to work with geofences, but it is easier to use Google's GeofencingApi. This APIs is part of Google's Location APIs. It includes Geofence, GeofencingRequest, GeofenceApi, GeofencingEvent, and GeofenceStatusCodes. In this tutorial, we use

I am doing it in a Service

GeolocationService

    public class GeolocationService extends Service implements LocationListener,
        GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {

    private Context mContext;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
//    private Location mLastLocation;
    private PendingIntent mGeofencePendingIntent;
    private String mLastUpdateTime;
    public static boolean isGeoFenceAdded = false;
    private boolean mUpdateGeoFence = false;
    private boolean mRemoveAllGeoFence = false;

    private static final long TIME_OUT = 100;

    @Override
    public void onCreate() {
        super.onCreate();

        mContext = GeolocationService.this;
        buildGoogleApiClient();
        createLocationRequest();

    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(mContext)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        /// FIXME: 2/15/2017 connect should be handled through onStart and onStop of Activity
        mGoogleApiClient.connect();
    }

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000);//set the interval in which you want to get locations
        mLocationRequest.setFastestInterval(2500);//if a location is available sooner you can get it (i.e. another app is using the location services)
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            if (intent.getAction() != null) {
                if (intent.getAction().equals(Constants.ACTION_UPDATE_GEOFENCE)) {
                    //// FIXME: 3/21/2017 you can also receive triggered location here..
                    mUpdateGeoFence = true;
                    isGeoFenceAdded = false;
                    mRemoveAllGeoFence = false;
                } else if (intent.getAction().equals(Constants.ACTION_ADD_GEOFENCE)) {
                    mUpdateGeoFence = false;
                    isGeoFenceAdded = false;
                    mRemoveAllGeoFence = false;
                } else if (intent.getAction().equals(Constants.ACTION_REMOVE_ALL_GEOFENCE)) {
                    mRemoveAllGeoFence = true;
                    isGeoFenceAdded = true;
                    mUpdateGeoFence = false;
                }
            }
        }
        //try this for null as http://stackoverflow.com/a/25096022/3496570
        ///return START_REDELIVER_INTENT;
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        startLocationUpdates(mContext);
    }

    @Override
    public void onConnectionSuspended(int i) {
        switch (i) {
            case CAUSE_SERVICE_DISCONNECTED:
                /*if (onLocationUpdateListener != null)
                    onLocationUpdateListener.onError(
                            Constants.ErrorType.SERVICE_DISCONNECTED);*/
                break;
            case CAUSE_NETWORK_LOST:
                /*if (onLocationUpdateListener != null)
                    onLocationUpdateListener.onError(
                            Constants.ErrorType.NETWORK_LOST);*/
                break;
        }

        //// FIXME: 3/2/2017 check is it right to check for re Connecting..
        //---  http://stackoverflow.com/a/27350444/3496570
        ///mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        /*if (onLocationUpdateListener != null)
            onLocationUpdateListener.onError(
                    Constants.ErrorType.CONNECTION_FAIL);*/

        //// FIXME: 3/3/2017 call a transparent activity and call startResolutionForresult from their and return result to service using action
        if (connectionResult.hasResolution()) {
            /*try {
                // !!!
                connectionResult.startResolutionForResult(this, REQUEST_CODE_RESOLVE_ERR);
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }*/
        } else {
            /*GoogleApiAvailability.getInstance().getErrorDialog(mContext, connectionResult.getErrorCode(), 0).show();
            return;*/
        }
    }

    @Override
    public void onLocationChanged(final Location currentLocation) {
        setupGeoFencePoints(currentLocation);
        /*if (onLocationUpdateListener != null && mLocation != null) {
            onLocationUpdateListener.onLocationChange(mLocation);
        }*/
    }

    private void setupGeoFencePoints(final Location currentLocation) {

        mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
//        mLastLocation = currentLocation;

        if (currentLocation != null && isGeoFenceAdded == false)
        {
            if (mUpdateGeoFence) {
                if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
                    LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient
                            , getGeofencePendingIntent()).setResultCallback(new ResultCallback<Status>() {
                        @Override
                        public void onResult(@NonNull Status status) {
                            if (status.isSuccess()) {
                                //if old geoFence's remove successfully then add new ones.
                                addGeoFences(currentLocation);
                            }
                        }
                    });
                }
            } else {
                addGeoFences(currentLocation);
            }
        }
        else if(isGeoFenceAdded && mRemoveAllGeoFence ){
            if (mGoogleApiClient != null && mGoogleApiClient.isConnected())
            {
                LocationServices.GeofencingApi.removeGeofences(mGoogleApiClient
                        , mGeofencePendingIntent).setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(@NonNull Status status) {
                        if (status.isSuccess()) {

                            mRemoveAllGeoFence = false;
                            isGeoFenceAdded = false;
                            //if old geoFence's remove successfully then do nothing.
                            stopLocationUpdate();

                            if (mGoogleApiClient != null && mGoogleApiClient.isConnected())
                                mGoogleApiClient.disconnect();
                        }
                    }
                });
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopLocationUpdate();

        if (mGoogleApiClient != null && mGoogleApiClient.isConnected())
            mGoogleApiClient.disconnect();
    }

    private void startLocationUpdates(final Context mContext) {

        if (ActivityCompat.checkSelfPermission(mContext,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(mContext,
                Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

//        mLastLocation = FusedLocationApi.getLastLocation(mGoogleApiClient);

        PendingResult<Status> pendingResult = FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);
        pendingResult.setResultCallback(new ResultCallback<Status>() {
            @Override
            public void onResult(@NonNull Status status) {
                //update it's code too.
                if (status.isSuccess()) {
                    Toast.makeText(mContext, "location Update Started",
                            Toast.LENGTH_SHORT).show();
                } else if (status.hasResolution()) {
                    Toast.makeText(mContext, "Open intent to resolve",
                            Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private void stopLocationUpdate() {
        //three types of constructor ..
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            FusedLocationApi.removeLocationUpdates(
                    mGoogleApiClient, this);
        }
    }

    public void addGeoFences(Location currentLocation) {
        if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            try {

                if (getGeofencingRequest(currentLocation) != null) {
                    LocationServices.GeofencingApi.addGeofences(
                            mGoogleApiClient,
                            // The GeofenceRequest object.
                            getGeofencingRequest(currentLocation),
                            // A pending intent that that is reused when calling removeGeofences(). This
                            // pending intent is used to generate an intent when a matched geofence
                            // transition is observed.
                            getGeofencePendingIntent()
                            //).await(TimeOut,TimeUnit.Miilisecponds);
                    ).setResultCallback(new ResultCallback<Status>() {
                        @Override
                        public void onResult(@NonNull Status status) {
                            if (status.isSuccess()) {
                                Toast.makeText(mContext, "Geo Fence Added", Toast.LENGTH_SHORT).show();

                                isGeoFenceAdded = true;
                                mRemoveAllGeoFence = false;
                                mUpdateGeoFence = false;

                                /// FIXME: 3/2/2017 I didn't have to draw it.
                                ///broadcastDrawGeoFenceOnMap();

                            } else {
                                String errorMessage = getErrorString(mContext, status.getStatusCode());
                                Toast.makeText(mContext, "Status Failed", Toast.LENGTH_SHORT).show();
                            }
                        }
                    }); // Result processed in onResult().
                }

            } catch (SecurityException securityException) {
                securityException.printStackTrace();
                // Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
                //logSecurityException(securityException);
            }
        }
    }

    private PendingIntent getGeofencePendingIntent() {
        if (mGeofencePendingIntent != null) {
            return mGeofencePendingIntent;
        }
        // Reuse the PendingIntent if we already have it.
        /// FIXME: 2/9/2017 Update the below class with a receiever..
        Intent intent = new Intent(mContext, GeofenceReceiver.class);///GeofenceTransitionsIntentService.class);
        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
        // addGeofences() and removeGeofences().
        /// FIXME: 3/1/2017 It must be reciever not IntentService
        mGeofencePendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        return mGeofencePendingIntent;
    }

    private GeofencingRequest getGeofencingRequest(Location mCurrentLocation) {

        /// FIXME: 2/13/2017 mLastLocation can be null because it will take time for the first time.
        /// this request should be called after first mLastLocation has been fetched..
        GeofencingRequest geofencingRequest = null;
        if (mCurrentLocation != null) {
            List<SimpleGeofence> simpleFenceList = SimpleGeofenceStore
                    .getInstance().getLatestGeoFences(mCurrentLocation);

            simpleFenceList.add(new SimpleGeofence("currentLocation",
                    mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude(),
                    100f, GEOFENCE_EXPIRATION_IN_MILLISECONDS,
                    Geofence.GEOFENCE_TRANSITION_EXIT));

            ListSharedPref.saveAnyTypeOfList(ListSharedPref.GEO_FENCE_LIST_KEY, simpleFenceList);

            GeofencingRequest.Builder geofencingRequestBuilder = new GeofencingRequest.Builder();
            geofencingRequestBuilder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);

            for (SimpleGeofence simpleGeofence : simpleFenceList)
                geofencingRequestBuilder.addGeofence(simpleGeofence.toGeofence());

            geofencingRequest = geofencingRequestBuilder.build();
        }
        // Return a GeofencingRequest.
        return geofencingRequest;
    }
}

GeofenceReceiver

public class GeofenceReceiver extends IntentService {
    public static final int NOTIFICATION_ID = 1;

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

    @Override
    protected void onHandleIntent(Intent intent) {
        GeofencingEvent geoEvent = GeofencingEvent.fromIntent(intent);

        Location triggredLocation = geoEvent.getTriggeringLocation();

        if (geoEvent.hasError()) {
            Log.d(HomeActivity.TAG, "Error GeofenceReceiver.onHandleIntent");
        } else {
            Log.d(HomeActivity.TAG, "GeofenceReceiver : Transition -> "
                    + geoEvent.getGeofenceTransition());

            int transitionType = geoEvent.getGeofenceTransition();

            if (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER
                    || transitionType == Geofence.GEOFENCE_TRANSITION_DWELL
                    || transitionType == Geofence.GEOFENCE_TRANSITION_EXIT) {
                List<Geofence> triggerList = geoEvent.getTriggeringGeofences();

                //if(triggerList.g)


                Type listType = new TypeToken<ArrayList<SimpleGeofence>>(){}.getType();
                List<SimpleGeofence> geoFenceList = GenericPref.readAnyTypeOfList(GenericPref.GEO_FENCE_LIST_KEY,listType);

                for (Geofence geofence : triggerList)
                {
                    /*SimpleGeofence sg = SimpleGeofenceStore.getInstance()
                            .getSimpleGeofences().get(geofence.getRequestId());*/

                    SimpleGeofence sg = null;
                    for(SimpleGeofence simpleGeofence : geoFenceList){
                        if(simpleGeofence.getId().equalsIgnoreCase(geofence.getRequestId())){
                            sg = simpleGeofence;
                            break;
                        }
                    }

                    String transitionName = "";
                    switch (transitionType) {
                        case Geofence.GEOFENCE_TRANSITION_DWELL:
                            transitionName = "dwell";
                            break;

                        case Geofence.GEOFENCE_TRANSITION_ENTER:
                            transitionName = "enter";

                            String date = DateFormat.format("yyyy-MM-dd hh:mm:ss",
                                    new Date()).toString();
                            EventDataSource eds = new EventDataSource(
                                    getApplicationContext());
                            eds.create(transitionName, date, geofence.getRequestId());
                            eds.close();

                            GeofenceNotification geofenceNotification = new GeofenceNotification(
                                    this);
                            if(sg != null){
                                geofenceNotification
                                        .displayNotification(sg, transitionType);
                            }
                            break;

                        case Geofence.GEOFENCE_TRANSITION_EXIT:
                            transitionName = "exit";
                            broadcastUpdateGeoFences();
                            //update your List
                            // Unregister all geoFences and reRegister it again
                            break;
                    }
                }
            }
        }
    }

    public void broadcastUpdateGeoFences() {
        //// FIXME: 3/2/2017 what if app is closed
        HomeActivity.geofencesAlreadyRegistered = false;
        MainActivity.isGeoFenceAdded = false;
        Intent intent = new Intent(Constants.RECEIVER_GEOFENCE);
        intent.putExtra("done", 1);
        sendBroadcast(intent);
    }
}

Geofencing API Tutorial for Android, Then when a user enters the geofence area, it will show notification and also do something. The only requirement I want for creating Geofences is� You create the geofence model using the data from the reminder. You use the GeofencingClient to add the geofence that you’ve just built with a geofencing request and a pending intent. More on this later. If the geofence is added successfully, you save the reminder and call the success argument.

My requirement was when I will click on map, then at that location, I am creating geo fencing circle. and showing notification when our current location is entering that fence and when exiting from it.

MapsActivity.java

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.location.Location;

import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofencingRequest;
import com.google.android.gms.location.LocationListener;

import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.MenuItem;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        LocationListener,
        GoogleMap.OnMapClickListener, ResultCallback<Status> {

    private GoogleMap mMap;
    SupportMapFragment mapFragment;
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    Location mLastLocation;
    Marker mCurrLocationMarker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }


    /**
     * Manipulates the map once available.
     * This callback is triggered when the map is ready to be used.
     * This is where we can add markers or lines, add listeners or move the camera. In this case,
     * we just add a marker near Sydney, Australia.
     * If Google Play services is not installed on the device, the user will be prompted to install
     * it inside the SupportMapFragment. This method will only be triggered once the user has
     * installed Google Play services and returned to the app.
     */
    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);

        mMap.setOnMapClickListener(this);

        //Initialize Google Play Services
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)
                    == PackageManager.PERMISSION_GRANTED) {
                //Location Permission already granted
                buildGoogleApiClient();
                mMap.setMyLocationEnabled(true);
            } else {
                //Request Location Permission
                checkLocationPermission();
            }
        } else {
            buildGoogleApiClient();
            mMap.setMyLocationEnabled(true);
        }
    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnected(Bundle bundle) {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
    }


    @Override
    public void onLocationChanged(Location location) {
        mLastLocation = location;
        if (mCurrLocationMarker != null) {
            mCurrLocationMarker.remove();
        }

        //Place current location marker
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(latLng);
        markerOptions.title("Current Position");
        markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
        mCurrLocationMarker = mMap.addMarker(markerOptions);

        //move map camera
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));

        Location targetLocation = new Location("");//provider name is unnecessary
        targetLocation.setLatitude(18.569557d);//your coords of course
        targetLocation.setLongitude(73.879369d);

       // This is also working

       /* if (location.distanceTo(targetLocation) < 100) {
            // bingo!
            Toast.makeText(this, "You are at MplusSoft Technology", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "You are not at your place.", Toast.LENGTH_SHORT).show();

        }*/

    }


    public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

    private void checkLocationPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.ACCESS_FINE_LOCATION)) {

                // Show an explanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
                new AlertDialog.Builder(this)
                        .setTitle("Location Permission Needed")
                        .setMessage("This app needs the Location permission, please accept to use location functionality")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                //Prompt the user once explanation has been shown
                                ActivityCompat.requestPermissions(MapsActivity.this,
                                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                        MY_PERMISSIONS_REQUEST_LOCATION);
                            }
                        })
                        .create()
                        .show();


            } else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // location-related task you need to do.
                    if (ContextCompat.checkSelfPermission(this,
                            Manifest.permission.ACCESS_FINE_LOCATION)
                            == PackageManager.PERMISSION_GRANTED) {

                        if (mGoogleApiClient == null) {
                            buildGoogleApiClient();
                        }
                        mMap.setMyLocationEnabled(true);
                    }

                } else {

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

    @Override
    public void onPause() {
        super.onPause();

        //stop location updates when Activity is no longer active
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, (com.google.android.gms.location.LocationListener) this);
        }
    }


    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }


    //------------------------------------- Geo fencing -------------------------------------


    @Override
    protected void onResume() {
        super.onResume();

    }

    @Override
    public void onResult(@NonNull Status status) {
        Log.e("onResult: ", "onResult: " + status);
        if (status.isSuccess()) {
            drawGeofence();
        } else {
            // inform about fail
        }
    }


    @Override
    public void onMapClick(LatLng latLng) {
        markerForGeofence(latLng);
    }

    private Marker geoFenceMarker;

    // Create a marker for the geofence creation
    private void markerForGeofence(LatLng latLng) {
        Log.e("markerForGeofence", "markerForGeofence(" + latLng + ")");
        String title = latLng.latitude + ", " + latLng.longitude;
        // Define marker options
        MarkerOptions markerOptions = new MarkerOptions()
                .position(latLng)
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE))
                .title(title);
        if (mMap != null) {
            // Remove last geoFenceMarker
            if (geoFenceMarker != null)
                geoFenceMarker.remove();

            geoFenceMarker = mMap.addMarker(markerOptions);

            startGeofence();
        }
    }


    private static final long GEO_DURATION = 60 * 60 * 1000;
    private static final String GEOFENCE_REQ_ID = "My Geofence";
    private static final float GEOFENCE_RADIUS = 50.0f; // in meters

    // Create a Geofence
    private Geofence createGeofence(LatLng latLng, float radius) {
        Log.e("createGeofence", "createGeofence");
        return new Geofence.Builder()
                .setRequestId(GEOFENCE_REQ_ID)
                .setCircularRegion(latLng.latitude, latLng.longitude, radius)
                .setExpirationDuration(GEO_DURATION)
                .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER
                        | Geofence.GEOFENCE_TRANSITION_EXIT)
                .build();
    }

    // Create a Geofence Request
    private GeofencingRequest createGeofenceRequest(Geofence geofence) {
        Log.e("createGeofenceRequest", "createGeofenceRequest");
        return new GeofencingRequest.Builder()
                .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
                .addGeofence(geofence)
                .build();
    }

    private PendingIntent geoFencePendingIntent;
    private final int GEOFENCE_REQ_CODE = 0;

    @SuppressLint("LongLogTag")
    private PendingIntent createGeofencePendingIntent() {
        Log.e("createGeofencePendingIntent", "createGeofencePendingIntent");
        if (geoFencePendingIntent != null)
            return geoFencePendingIntent;

        Intent intent = new Intent(this, GeofenceTrasitionService.class);
        return PendingIntent.getService(
                this, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    // Add the created GeofenceRequest to the device's monitoring list
    private void addGeofence(GeofencingRequest request) {
        Log.e("addGeofence", "addGeofence");
        //if (checkPermission())
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        LocationServices.GeofencingApi.addGeofences(
                mGoogleApiClient,
                request,
                createGeofencePendingIntent()
        ).setResultCallback(this);
    }



    // Draw Geofence circle on GoogleMap
    private Circle geoFenceLimits;
    private void drawGeofence() {
        Log.e("drawGeofence()", "drawGeofence()");

        if ( geoFenceLimits != null )
            geoFenceLimits.remove();

        CircleOptions circleOptions = new CircleOptions()
                .center( geoFenceMarker.getPosition())
                .strokeColor(Color.argb(50, 70,70,70))
                .fillColor( Color.argb(100, 150,150,150) )
                .radius( GEOFENCE_RADIUS );
        geoFenceLimits = mMap.addCircle( circleOptions );
    }



    // Start Geofence creation process
    private void startGeofence() {
        Log.e("startGeofence", "startGeofence()");
        if( geoFenceMarker != null ) {
            Geofence geofence = createGeofence( geoFenceMarker.getPosition(), GEOFENCE_RADIUS );
            GeofencingRequest geofenceRequest = createGeofenceRequest( geofence );
            addGeofence( geofenceRequest );
        } else {
            Log.e("Geofence marker is null", "Geofence marker is null");
        }
    }

    static Intent makeNotificationIntent(Context geofenceService, String msg)
    {
        Log.e("makeNotificationIntent ",msg);
        return new Intent(geofenceService,MainActivity.class);
    }

}

GeofenceTrasitionService.java

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.util.Log;

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

import java.util.ArrayList;
import java.util.List;

public class GeofenceTrasitionService extends IntentService {

    private static final String TAG = GeofenceTrasitionService.class.getSimpleName();
    public static final int GEOFENCE_NOTIFICATION_ID = 0;

    public GeofenceTrasitionService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // Retrieve the Geofencing intent
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);

        // Handling errors
        if ( geofencingEvent.hasError() ) {
            String errorMsg = getErrorString(geofencingEvent.getErrorCode() );
            Log.e( TAG, errorMsg );
            return;
        }

        // Retrieve GeofenceTrasition
        int geoFenceTransition = geofencingEvent.getGeofenceTransition();
        // Check if the transition type
        if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
                geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT ) {
            // Get the geofence that were triggered
            List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
            // Create a detail message with Geofences received
            String geofenceTransitionDetails = getGeofenceTrasitionDetails(geoFenceTransition, triggeringGeofences );
            // Send notification details as a String
            sendNotification( geofenceTransitionDetails );
        }
    }

    // Create a detail message with Geofences received
    private String getGeofenceTrasitionDetails(int geoFenceTransition, List<Geofence> triggeringGeofences) {
        // get the ID of each geofence triggered
        ArrayList<String> triggeringGeofencesList = new ArrayList<>();
        for ( Geofence geofence : triggeringGeofences ) {
            triggeringGeofencesList.add( geofence.getRequestId() );
        }

        String status = null;
        if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER )
            status = "Entering ";
        else if ( geoFenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT )
            status = "Exiting ";
        return status + TextUtils.join( ", ", triggeringGeofencesList);
    }

    // Send a notification
    private void sendNotification( String msg ) {
        Log.i(TAG, "sendNotification: " + msg );

        // Intent to start the main Activity
        Intent notificationIntent = MapsActivity.makeNotificationIntent(
                getApplicationContext(), msg
        );

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MapsActivity.class);
        stackBuilder.addNextIntent(notificationIntent);
        PendingIntent notificationPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

        // Creating and sending Notification
        NotificationManager notificatioMng =
                (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
        notificatioMng.notify(
                GEOFENCE_NOTIFICATION_ID,
                createNotification(msg, notificationPendingIntent));
    }

    // Create a notification
    private Notification createNotification(String msg, PendingIntent notificationPendingIntent) {
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
        notificationBuilder
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setColor(Color.RED)
                .setContentTitle(msg)
                .setContentText("Geofence Notification!")
                .setContentIntent(notificationPendingIntent)
                .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND)
                .setAutoCancel(true);
        return notificationBuilder.build();
    }

    // Handle errors
    private static String getErrorString(int errorCode) {
        switch (errorCode) {
            case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE:
                return "GeoFence not available";
            case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES:
                return "Too many GeoFences";
            case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS:
                return "Too many pending intents";
            default:
                return "Unknown error.";
        }
    }
}

activity_maps.xml

    <?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MapsActivity" />

manifest

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


  <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />

        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps"> <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter></activity>

        <service android:name=".GeofenceTrasitionService"/>

build.gradle

implementation 'com.android.support:appcompat-v7:28.0.0-rc01'
implementation 'com.google.android.gms:play-services-maps:15.0.1'
implementation 'com.google.android.gms:play-services-location:15.0.1'

Setting up Geofencing with Notifications on Android, <uses-permission android:name="android.permission.INTERNET" />. Geofencing needs Google Services API. Open your build.gradle and add� Teams. Q&A for Work. Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information.

How to create Geofences on Android?, A step by step guide in creating a Geofence application in android and making use of BroadcastReciever to start a Service when that location is reached. You can create a list of geofence objects by setting the latitude, longitude, radius, duration, and transition types of each geofence. The transition types indicate the events that trigger the geofence, such as when users enter or exit a geofence. Once you have a list of geofences, you can add it to a geofencing request.

Geofencing in Android. What is Geofence?, Geofencing combines awareness of the user's current location with awareness of nearby features, defined as the user's proximity to locations that may be of� To use geofencing, start by defining the geofences you want to monitor. Although you usually store geofence data in a local database or download it from the network, you need to send a geofence to Location Services as an instance of Geofence, which you create with Geofence.Builder.

How to create a geofence app in android. | by Hari Lee, This detailed android video focused vividly on Android GeoFencing step by step guide of how Duration: 1:10:22 Posted: Apr 18, 2017 Basic Android development, as taught in Developing Android Apps with Kotlin; What you'll learn. How to check user permissions. How to check device settings. How to add Broadcast Receivers. How to add geofences. How to handle geofence transitions. How to mock locations in the emulator. The app you will create in this codelab is a Treasure Hunt game.

Comments
  • In onResult, is there suppose to be @Override at the top? And im going red text at GeofenceErrorMessages in GeofenceErrorMessages.getErrorString(this, status.getStatusCode()); I cant find GeoFenceErrorMessages class
  • Hi, the @Override is necessary, because it will be overriding the default method implementation of onResult. The GeoFenceErrorMessages class is a custom class created to get the error id of the geofence and return a an error message, this part is not necessary for the geofence to work, but it's a good practice, more information can be found at this course at Udacity: udacity.com/course/google-location-services-on-android--ud876-1
  • @MarcolaCarr do we need to declare GeofenceTransitionsIntentService in manifest file under application tag?