简体   繁体   中英

Android geofence transition triggers

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();
}

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.

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM