Android geofence with mock location provider
Asked Answered
T

6

7

I have started developing on Android with last Location services feature : Geofences !! Is there any known problem with mock location provider ? Following example here (https://developer.android.com/training/location/geofencing.html) my intent service never fired even if the current location is inside geofence. I'm using FakeGPS android app as mock location provider and if I simulate a route I see the location changes on Google Maps app, so the mock location provider is working well. Any ideas ?

Thanks. Paolo.

Terrel answered 11/6, 2013 at 16:16 Comment(0)
O
4

I tried forever to get this to work. What a pain Google! Since it says geofences can easily be tested using mocks.

The magic trick is to use the provider name "network" in the Location passed to setMockLocation.

    Location location = new Location("network");
    location.setLatitude(latitude);
    location.setLongitude(longitude);
    location.setTime(new Date().getTime());
    location.setAccuracy(3.0f);
    location.setElapsedRealtimeNanos(System.nanoTime());

    LocationServices.FusedLocationApi.setMockLocation(_googleApiClient, location);
Osmo answered 29/9, 2014 at 21:21 Comment(3)
Don't you have to call LocationServices.FusedLocationApi.setMockMode(_googleApiClient, true) first?Kristin
Do you have a link that shows that the LocationServices.GeofencingApi actually uses LocationServices.FusedLocationApi for mocking? I have not seen any evidence that it is true.Ingrain
Oh my! This was a painful exercise. This is still relevant. Thank you!Tenant
S
2

Actually Intent service used in the mentioned example works good if your app is in foreground but when the app is in background, this IntentService is never called.So we need to use Broadcast-Receiver instead of Intent service.

I found this blog helpful in getting solution.

http://davehiren.blogspot.in/2015/01/android-geofence-stop-getting.html

Seesaw answered 3/4, 2017 at 9:37 Comment(4)
A link to a solution is welcome, but please ensure your answer is useful without it: add context around the link so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. Answers that are little more than a link may be deleted.Cristinacristine
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewOvercareful
You should not Downvote the answer unless until, you have clear understanding of question and its solution. @OvercarefulSeesaw
thanks!! @M.A.R for pointing out the error, I have edited the answer with the required solution.Seesaw
N
1

Geofences use FusedLocationProviderApi so to mock them you have to use FusedLocationProviderApi.setMockLocation

Nylon answered 4/2, 2015 at 13:56 Comment(1)
This interface is deprecated. Use the GoogleApi-based API FusedLocationProviderClient instead.Majormajordomo
J
0

Make sure to enable mock locations on your phone. Select Settings->Developer Options->"Allow mock locations".

Justajustemilieu answered 23/1, 2015 at 22:42 Comment(0)
L
0

LocationServices.FusedLocationApi.setMockMode(googleApiClient, true) needs to be used before setting Mock Location.

Loos answered 28/2, 2015 at 10:36 Comment(0)
O
0

You can use broadcast receiver instead of activity like this

public class GeofenceReceiver extends BroadcastReceiver
implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    ResultCallback<Status>{

GoogleApiClient mGoogleApiClient;
PendingIntent mGeofencePendingIntent ;
Context mContext;

@Override
public void onReceive(Context context, Intent intent) {
    mContext = context;
    mGoogleApiClient = new GoogleApiClient.Builder(mContext)
            .addOnConnectionFailedListener(this)
            .addConnectionCallbacks(this)
            .addApi(LocationServices.API)
            .build();

    mGoogleApiClient.connect();
}



@Override
public void onConnected(@Nullable Bundle bundle) {
    try {
        LocationServices.GeofencingApi.addGeofences(
                mGoogleApiClient,
                // The GeofenceRequest object.
                getGeofencingRequest(),
                getGeofencePendingIntent()
        ).setResultCallback(this); // Result processed in onResult().
    } catch (SecurityException securityException) {
        Log.i(getClass().getSimpleName(),securityException.getMessage());
    }
}

// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
@Override
public void onConnectionSuspended(int i) {

}

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

}

/**
 * Runs when the result of calling addGeofences() and removeGeofences() becomes available.
 * Either method can complete successfully or with an error.
 *
 * Since this activity implements the {@link ResultCallback} interface, we are required to
 * define this method.
 *
 * @param status The Status returned through a PendingIntent when addGeofences() or
 *               removeGeofences() get called.
 */
@Override
public void onResult(@NonNull Status status) {
    if (status.isSuccess()) {
        Log.i(getClass().getSimpleName(),"Success");
    } else {
        // Get the status code for the error and log it using a user-friendly message.
        Log.i(getClass().getSimpleName(),getErrorString(status.getStatusCode()));
    }
}

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

private List<Geofence> getGeofecne(){
    List<Geofence> mGeofenceList = new ArrayList<>();

    //add one object
    mGeofenceList.add(new Geofence.Builder()
            // Set the request ID of the geofence. This is a string to identify this
            // geofence.
            .setRequestId("key")

            // Set the circular region of this geofence.
            .setCircularRegion(
                    25.768466, //lat
                    47.567625, //long
                    50) // radios

            // Set the expiration duration of the geofence. This geofence gets automatically
            // removed after this period of time.
            //1000 millis  * 60 sec * 5 min
            .setExpirationDuration(1000 * 60 * 5)

            // Set the transition types of interest. Alerts are only generated for these
            // transition. We track entry and exit transitions in this sample.
            .setTransitionTypes(
                    Geofence.GEOFENCE_TRANSITION_DWELL)
            //it's must to set time in millis with dwell transition
            .setLoiteringDelay(3000)
            // Create the geofence.
            .build());

    return mGeofenceList;

}

private PendingIntent getGeofencePendingIntent() {
    // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    Intent intent = new Intent(mContext, GeofenceTransitionsIntentService.class);
    return PendingIntent.getService(mContext, 0, intent, PendingIntent.
            FLAG_UPDATE_CURRENT);
}

}

check out my repo, there is a full example of using geofence https://github.com/3zcs/Geofence

Orientate answered 3/4, 2017 at 20:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.