4

I'm building an app which includes googles geofences, which i created with both ENTER and EXIT transitions. The problem occurs when turning "Location" on, when inside my geofence, it triggeres both transitions, when only the ENTER transition should trigger. Ive set both ENTER and EXIT as intitialTrigger().

How this can be possibel ?

Is it a fault in the google api or have i done something wrong in the builder. Thanks in advance.

@Override
public void onResult(Result result) {
    Status s = result.getStatus();
    Log.d(TAG, "onResult(...)" + s.isSuccess());
    if (!s.isSuccess()) {
        Log.d(TAG, "statuskode = " + s.getStatusCode() +
                "  noget gik galt, sandsynlighvis blev gps slået fra = statuscode 1000");
    }
}

private GeofencingRequest createGeoFences() {
    return new GeofencingRequest.Builder()
            .addGeofence(geoFenceBuilder(Constants.LOCATION_BALLERUP, "ballerup_req_id"))
            .addGeofence(geoFenceBuilder(Constants.LOCATION_AALBORG, "aalborg_req_id"))
            .addGeofence(geoFenceBuilder(Constants.LOCATION_ESBJERG, "esbjerg_req_id"))
            .addGeofence(geoFenceBuilder(Constants.LOCATION_ÅRHUS, "århus_req_id"))
                    //  .addGeofence(geoFenceBuilder(Constants.LOCATION_TAASTRUP, 44))
            .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER | GeofencingRequest.INITIAL_TRIGGER_EXIT)
            .build();
}

private Geofence geoFenceBuilder(LatLng location, String requestId) {

    return new Geofence.Builder().setCircularRegion(location.latitude, location.longitude, TARGET_RADIUS)
            .setExpirationDuration(Geofence.NEVER_EXPIRE)
            .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
            .setRequestId(requestId)
            .setNotificationResponsiveness(NOTIFICATION_DELAY)
            .build();
}
Mads Gade
  • 53
  • 1
  • 6

2 Answers2

2

This might be some weird bug on Google's Geofence APIs part. Also, it is kind of weird to have both ENTER and EXIT events as initial triggers. Here's an easy solution to dynamically call setInitialTrigger(), and avoid this altogether. Before calling createGeoFences(), get a GPS point and check the distance from that point to the center point of the geofence. If it is outside the geofence, just pass a value to set the initial trigger to GEOFENCE_TRANSITION_ENTER, otherwise, set it to GEOFENCE_TRANSITION_EXIT.

As for why it is doing this, here is my thought on it, although I haven't tested it. Google may be getting the last known location, which could be outside the geofence initially, thus registering the GEOFENCE_TRANSITION_EXIT event. Then it'll start up it's location stack, see that the phone is actually inside the geofence, then register the GEOFENCE_TRANSITION_ENTER event.

Pablo Baxter
  • 2,144
  • 1
  • 17
  • 36
  • 1
    Hey pablo. A good reply, i think it sounds like a very likely explination of that faulty triggering. Your suggestion is also fine, though my initial reason for not doing this is; if google api requires custom handling then you might aswell create your own geofence implementation i think so. Also its not that weird to want both triggers. Imagine if the gps is turned of inside a geofence, and then turned back on outside the fence. I still want the location updated, so that my server dont consider me inside the geofence. Thx for the reply it was good. – Mads Gade Feb 24 '16 at 10:00
  • Building your own geofence solution that somewhat works and remains low power is pretty hard. I am part of a team that strived to do just that. Also, the weird part was having both ENTER and EXIT set as the initial trigger. Not wrong, but I would have the app assume we are outside a geofence, unless we explicitly tell it we have entered a geofence. Then we wait for the EXIT event trigger. Hope all goes well for your app! Edit: FYI, our stuff works... not just somewhat. :-) – Pablo Baxter Feb 24 '16 at 22:18
0

You need to register an IntentService that can handle the triggers

public class GeofenceTransitionsIntentService extends IntentService {
   ...
protected void onHandleIntent(Intent intent) {

    GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);   
    // Get the transition type.
    int geofenceTransition = geofencingEvent.getGeofenceTransition();

    // Test that the reported transition was of interest.
    if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ) {
        //TODO: on Transition Enter
    }else if(geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT){
        //TODO: on Transition Exit
    }else{
      Log.e(GEOFENCE, "Event not handled",
                geofenceTransition));
    }

explained here: http://developer.android.com/training/location/geofencing.html

If you need to know if you are inside a geofence you could loop you current list of geofence locations and check if one of them is close enought to trigger?

Something like this:

public Location insideGeofenceLocation(Location currentLocation, ArrayList<Location> listOfGeofenceLocations, float triggerRadius) {
    for (Location geoFenceLocation : listOfGeofenceLocations) {
        if (currentLocation.distanceTo(geoFenceLocation) < triggerRadius)
            return geoFenceLocation;
    }
    return null;
}

check current location:

Location geofenceLocation = insideGeofenceLocation(locationClient.getLastLocation(), listOfGeofenceLocations, TARGET_RADIUS);
if(geofenceLocation!=null){
    // TODO: update
}
TouchBoarder
  • 6,422
  • 2
  • 52
  • 60
  • 2
    thx for the answer. Perhaps i didnt explain my self clear enough. The problem is that the wrong transition triggers, as when turning "location" on inside a geofence, the EXIT-transition triggers, when only the ENTER-transition should trigger... Hence the problem is, how to remove/solve the false EXIT-transition triggering. – Mads Gade Dec 14 '15 at 12:27
  • Sounds correct, if you are inside the geofence you can only trigger an exit or dwell transition. To trigger a enter transition you need to transit into the geofence from the outside. – TouchBoarder Dec 14 '15 at 12:34