title: Geofencing doesn't work?
body: <p>So I've been trying simple geofencing applications from the internet but none of them seems to work. In the following example a notification should be triggered when the longitude and the latitude of the phone meet the longitude and the latitude defined in the constants class. I tested it with the emulator but when I change the emulator gps coordinates accordingly, nothing happens.
  According to the documentation there are some possible reasons for alerts not working as expected:</p>
  
  <ul>
  <li>Accurate location isn't available inside your geofence or your
  geofence is too small </li>
  <li>Wi-Fi is turned off on the device.</li>
  <li>There is no reliable network connectivity inside your geofence.</li>
  <li>Alerts can be late.</li>
  </ul>
  
  <p>I get this message on android studio:
  <a href="https://i.stack.imgur.com/8mH8x.png" rel="nofollow noreferrer">https://drive.google.com/open?id=12VjaB5BNjdIrOD5QVJWLoRwnXEZq6KKB</a></p>
  
  <p>Here is my log:</p>
  
  <pre><code>02-01 13:42:09.932 14925-14925/? I/zygote: Not late-enabling -Xcheck:jni (already on)
  02-01 13:42:09.955 14925-14925/? W/zygote: Unexpected CPU variant for X86 using defaults: x86
  02-01 13:42:09.993 14925-14932/? E/zygote: Failed writing handshake bytes (-1 of 14): Broken pipe
  02-01 13:42:09.993 14925-14932/? I/zygote: Debugger is no longer active
  02-01 13:42:10.315 14925-14925/? I/InstantRun: starting instant run server: is main process
  02-01 13:42:10.725 14925-14942/? D/OpenGLRenderer: HWUI GL Pipeline
  02-01 13:42:10.784 14925-14942/? I/zygote: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
  02-01 13:42:10.784 14925-14942/? I/OpenGLRenderer: Initialized EGL, version 1.4
  02-01 13:42:10.784 14925-14942/? D/OpenGLRenderer: Swap behavior 1
  02-01 13:42:10.785 14925-14942/? W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
  02-01 13:42:10.785 14925-14942/? D/OpenGLRenderer: Swap behavior 0
  02-01 13:42:10.810 14925-14942/? D/EGL_emulation: eglCreateContext: 0x9cb60b60: maj 2 min 0 rcv 2
  02-01 13:42:10.872 14925-14942/? D/EGL_emulation: eglMakeCurrent: 0x9cb60b60: ver 2 0 (tinfo 0xa60b35d0)
  02-01 13:42:10.963 14925-14942/? D/EGL_emulation: eglMakeCurrent: 0x9cb60b60: ver 2 0 (tinfo 0xa60b35d0)
  02-01 13:42:11.480 14925-14925/com.shah.kaushal28.fence I/Choreographer: Skipped 31 frames!  The application may be doing too much work on its main thread.
  </code></pre>
  
  <p>MainActivity.java class</p>
  
  <pre><code>package com.shah.kaushal28.fence;
  
  import android.app.PendingIntent;
  import android.content.Intent;
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.util.Log;
  import android.view.View;
  import android.widget.Button;
  import android.widget.Toast;
  
  import com.google.android.gms.common.ConnectionResult;
  import com.google.android.gms.common.api.GoogleApiClient;
  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.LocationServices;
  import com.google.android.gms.maps.model.LatLng;
  
  import java.util.ArrayList;
  import java.util.Map;
  
  public class MainActivity extends AppCompatActivity implements
          GoogleApiClient.ConnectionCallbacks,
          GoogleApiClient.OnConnectionFailedListener,
          ResultCallback&lt;Status&gt;{
  
      private static final String TAG = "";
      protected ArrayList&lt;Geofence&gt; mGeofenceList;
      protected GoogleApiClient mGoogleApiClient;
      private Button mAddGeofencesButton;
  
      @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&lt;Geofence&gt;();
  
          // 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();
          Log.e(TAG, "building client successful");
      }
  
      public void populateGeofenceList() {
          for (Map.Entry&lt;String, LatLng&gt; 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());
          }
          Log.e(TAG, "geofence populated");
      }
  
      @Override
      protected void onStart() {
          super.onStart();
          if (!mGoogleApiClient.isConnecting() || !mGoogleApiClient.isConnected()) {
              mGoogleApiClient.connect();
              Log.e(TAG, "mGoogleApiClient connected");
          }
      }
  
      @Override
      protected void onStop() {
          super.onStop();
          if (mGoogleApiClient.isConnecting() || mGoogleApiClient.isConnected()) {
              mGoogleApiClient.disconnect();
              Log.e(TAG, "mGoogleApiClient disconnected");
          }
      }
  
      @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.
          }
          Log.e(TAG, "geofence added");
  
      }
  
      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.
              System.out.println("Error");
              Toast.makeText(
                      this,
                      "Error",
                      Toast.LENGTH_SHORT
              ).show();
          }
      }
  }
  </code></pre>
  
  <p>GeofenceTransitionsIntentService.java class</p>
  
  <pre><code>package com.shah.kaushal28.fence;
  
  import android.app.IntentService;
  import android.app.NotificationManager;
  import android.app.PendingIntent;
  import android.content.Context;
  import android.content.Intent;
  import android.graphics.Color;
  import android.support.v4.app.NotificationCompat;
  import android.support.v4.app.TaskStackBuilder;
  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;
  
  /**
   * Created by Kaushal28 on 4/26/2017.
   */
  
  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) {
          Log.e(TAG, "Notification Triggered");
  
          // 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 &gt;= 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());
      }
  }
  </code></pre>
  
  <p>Constants.java class</p>
  
  <pre><code>package com.shah.kaushal28.fence;
  
  /**
   * Created by Kaushal28 on 4/26/2017.
   */
  
  import com.google.android.gms.maps.model.LatLng;
  
  import java.util.HashMap;
  
  
  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&lt;String, LatLng&gt; LANDMARKS = new HashMap&lt;String, LatLng&gt;();
      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));
      }
  }
  </code></pre>