Android Geofence triggers on enter/exit with no error but no GEOFENCE_TRANSITION_ flag

1.9k views Asked by At

I am monitoring for geofence transition using the code below

LocationServices.GeofencingApi
    .addGeofences(AssistApplication.getApiHelper().getClient(),
                  getGeofencingRequest(),
                  getPendingIntent(context,  
                              GeofenceTransitionIntentService.class))
    .setResultCallback(this);

This is how I build the GeofencingRequest

private GeofencingRequest getGeofencingRequest()
{
    return new GeofencingRequest.Builder()
            .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER |
                    GeofencingRequest.INITIAL_TRIGGER_EXIT)
            .addGeofence(getGeofence())
            .build();
}

private Geofence getGeofence()
{
    return new Geofence.Builder()
            .setRequestId(requestId)
            .setCircularRegion(latitude, longitude, 100)
            .setExpirationDuration(Geofence.NEVER_EXPIRE)
            .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
                    Geofence.GEOFENCE_TRANSITION_EXIT)
            .build();
}

The Geofence triggers correctly on enter and exit, but when I use getGeofenceTransition(), I am not getting any of the three GEOFENCE_TRANSITION_ flags.

protected void onHandleIntent(Intent intent)
{
    final GeofencingEvent event = GeofencingEvent.fromIntent(intent);
    if (event.hasError())
    {
        Log.e(TAG, getErrorMessage(event.getErrorCode()));
        return;
    }

    switch (event.getGeofenceTransition())
    {
        case Geofence.GEOFENCE_TRANSITION_EXIT:
            // Not triggered 
            break;
        case Geofence.GEOFENCE_TRANSITION_ENTER:
        case Geofence.GEOFENCE_TRANSITION_DWELL:
            // Not triggered
            break;
        default:
            // Triggered on exit and enter
    }
}

please advise on what I am missing here

3

There are 3 answers

3
Simon Hutton On

From the information in the question, I can't see any specific problems with your code, but I suspect the Intent you are processing isn't from a transition alert?

Personally I use a broadcast receiver to receive the Intent from the Geofence, with an IntentFilter used to filter it. The structure I use is as follows :-

Declare broadcast receiver in your Activity

private BroadcastReceiver passedGeofenceReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int geofenceTransition;

            // get the Geofencing Event
            GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
            if (geofencingEvent.hasError()) {
                return;
            }

            // Get the transition type.
            geofenceTransition = geofencingEvent.getGeofenceTransition();

            if ( geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER) {
                // etc etc 

Register this receiver in your Activity onCreate method :-

    // register this Activity as the receiver of Geofence notifications
    IntentFilter filter = new IntentFilter();
    filter.addAction("com.example.HIT_GEOFENCE");
    this.registerReceiver(this.passedGeofenceReceiver, filter);

On creation of a broadcast PendingIntent, set filter (mGeofencePendingIntent is a member PendingIntent variable) :-

private PendingIntent getGeofencePendingIntent() {
    // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }

    Intent hitGeofenceIntent = new Intent("com.example.HIT_GEOFENCE"); //- intent to send a broadcast

    mGeofencePendingIntent = PendingIntent.getBroadcast(this, 0, hitGeofenceIntent,  PendingIntent.FLAG_UPDATE_CURRENT);
    return mGeofencePendingIntent;
}

Monitor your geofences :-

private void monitorGeofences() {
    if ( <check permissions> ) {
        GeofencingRequest geofencingRequest = getGeofencingRequest();
        PendingIntent pendingIntent = getGeofencePendingIntent();
        LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, geofencingRequest, pendingIntent)
                        .setResultCallback(this); // Result callback fires 'onResult'
    }
}

I hope this helps.

0
MojoJojo On

@Jukurrpa, I was facing the same issue, i.e., No transition(-1) or GEOFENCE_TRANSITION_INVALID_TYPE: -1 and I implemented everything correctly except the flags for PendingIntent. I was using:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
else
    PendingIntent.FLAG_UPDATE_CURRENT

Your answer helped me a lot, I was searching for the solution for the last 4 days. Thank you so much.

1
Jukurrpa On

I've had the same issue working with geofences on Android 12. No transition (-1), no triggering location and no triggering geofences in the intent.

That was because I was using PendingIntent.FLAG_IMMUTABLE instead of PendingIntent.FLAG_MUTABLE when creating the pending intent.

So it should be created like this in the case of a broadcast intent:

PendingIntent.getBroadcast(
    context, 0,
    Intent(context, GeofenceBroadcastReceiver::class.java),
    PendingIntent.FLAG_UPDATE_CURRENT or
        (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0)
)