title: GeoFence Not Triggered w/Mock Location
body: <p>I am trying to test GeoFences for a location aware application.  I have gotten as many as 11 consecutive successes, but that is typically followed by dozens of failures.  Rebooting the device does not help.  Uninstalling/reinstalling does not help.  Disabling location, re-enabling location does not help.  Changing the devices Location Accuracy settings does not help.</p>
  
  <p>I've tested on v2.3.4, v4.0.3, v4.4.2, v4.4.4 and 2 v5.0.1 physical devices.  One of the Lollipop devices is a device with cellular service.  The remaining devices are SIMless and used for testing only.  Side note: the devices without service struggle with setting their location via MockLocation, but if they manage to set their location they almost never register a fence entry/exit.</p>
  
  <p>Location is being updated via Mock Location well enough, but the GeoFence(s) are not being triggered with any reliability.</p>
  
  <p>I've Googled it.  I've looked at the documentation on developer.android.com site.  I've searched StackOverflow.  In fact, many of the suggestions made by others have been implemented in the code below.</p>
  
  <p>So, how can I reliably trigger my GeoFence using MockLocation?</p>
  
  <pre><code>import android.location.Location;
  import android.location.LocationManager;
  
  public class GeoFenceTester extends ActivityInstrumentationTestCase2&lt;GeoFenceTesterActivity&gt; {
  
  
      public static final String TAG = GeoFenceTester.class.getSimpleName();
  
      private LocationManager locationManager;
      private Activity activityUnderTest;
  
      protected void setUp() throws Exception {
          super.setUp();
          activityUnderTest = getActivity();
          /*
              MOCK Locations are required for these tests.  If the user has not enabled MOCK Locations
              on the device or emulator these tests cannot work.
           */
          if (Settings.Secure.getInt(activityUnderTest.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) {
              throw new RuntimeException("Mock locations are currently disabled in Settings - These tests require mock locations");
          }
  
          Log.i(TAG, "Setup MOCK Location Providers");
          locationManager = (LocationManager) activityUnderTest.getSystemService(Context.LOCATION_SERVICE);
  
          Log.i(TAG, "GPS Provider");
          locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, true, false, false, false, false, false, Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
          locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
  
          Log.i(TAG, "Network Provider");
          locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER, true, false, true, false, false, false, false, Criteria.POWER_MEDIUM, Criteria.ACCURACY_FINE);
          locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true);
  
          if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.KITKAT) {
              Log.wtf(TAG, String.format("Location Accuracy: %1$d", Settings.Secure.getInt(activityUnderTest.getContentResolver(), Settings.Secure.LOCATION_MODE)));
          }
  
          /* Our EventBus for onEvent() callbacks */
          EventBus.getDefault().register(this);
      }
  
      protected void tearDown() {
          /* Our EventBus for onEvent() callbacks */
          EventBus.getDefault().unregister(this);
  
          locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
          locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER);
          locationManager = null;
  
          activityUnderTest = null;
  
          super.tearDown();
      }
  
      public void testGeoFence() {
  
          /*
              Using one or the other or both of these makes no difference.
          */
          Location mockGpsLocation = new Location(LocationManager.GPS_PROVIDER);
          mockGpsLocation.setLatitude(32.652411);
          mockGpsLocation.setLongitude(-79.938063);
          mockGpsLocation.setAccuracy(1.0f);
          mockGpsLocation.setTime(System.currentTimeMillis());
  
          Location mockNetworkLocation = new Location(LocationManager.NETWORK_PROVIDER);
          mockNetworkLocation.setLatitude(32.652411);
          mockNetworkLocation.setLongitude(-79.938063);
          mockNetworkLocation.setAccuracy(1.0f);
          mockNetworkLocation.setTime(System.currentTimeMillis());
  
          /*
              setElapsedRealtimeNanos() was added in API 17
           */
          if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.JELLY_BEAN_MR1) {
              mockGpsLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
              mockNetworkLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
          }
  
          try {
              Method locationJellyBeanFixMethod = Location.class.getMethod("makeComplete");
              if (locationJellyBeanFixMethod != null) {
                  locationJellyBeanFixMethod.invoke(mockGpsLocation);
                  locationJellyBeanFixMethod.invoke(mockNetworkLocation);
              }
          } catch (Exception e) {
              // There's no action to take here.  This is a fix for Jelly Bean and no reason to report a failure.
          }
  
          for (int i = 0; i &lt; 30; i++){
              Log.i(TAG, String.format("Iterating over our location ... (%1$d)", i));
              locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, mockGpsLocation);
              locationManager.setTestProviderLocation(LocationManager.NETWORK_PROVIDER, mockNetworkLocation);
              try {
                  Thread.sleep(1000);
              } catch (Exception e) {
                  Log.e(TAG, e.getMessage(), e);
              }
          }
      }
  
      public void onEvent(final GeoFenceUpdateEvent event) {
          // This doesn't get called about 9/10 times.
          // I have a GeoFence with a 5000m radius around 32.652411, -79.938063
      }
  
      public void onEvent(final LocationUpdateEvent event) {
          // This gets called without incident and event.getLatitude() &amp; event.getLongitude() are correct.
      }
  
  }
  </code></pre>