Search code examples
androidgoogle-mapsgeolocationlocationandroid-geofence

Continues Trigger GeoFence Event


GeoFence triggering issue

I have setup geofence in my app, I am using IntetnService for the handle trigger event.

My issue is with trigger event many time.

Suppose i am at 1 Location inside Geofence, unfortunately some time enter or exit event trigger, Then i do like check the geoEvent.getTriggerdLocation() properties and check with geo fence radius,

if the trigger location to geo fence location distance greater then geofecen radius then an then i will release my exit event functionality,

but eventually geofence trigger event 2 3 km far even i already entered in fence and my above logic will fail. see snap

enter image description here

i want some solid fix for these.

Location is on with High priority

this will happening more when i will near to border of fence

Add geo fence list, as of now i am using only one fence.

mGeofenceList.add(new Geofence.Builder().setRequestId(String.valueOf(loGeoFenceModels.liGeoFenceID))
                    .setCircularRegion(loGeoFenceModels.ldGeoLatitude, loGeoFenceModels.ldGeoLongitude,
                            loGeoFenceModels.lfRadius)
                    .setExpirationDuration(Geofence.NEVER_EXPIRE)
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
                    .build());

PendidngIntentService

moGeofencePendingIntent = getGeofencePendingIntent();
        LocationServices.GeofencingApi
                .addGeofences(moLocationClient, getGeofencingRequest(), moGeofencePendingIntent)
                .setResultCallback(this);

getGeofencingRequest() AND moGeofencePendingIntent

private GeofencingRequest getGeofencingRequest() {
    return new GeofencingRequest.Builder().setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
            .addGeofences(mGeofenceList).build();
}



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

    Intent intent = new Intent(moContext, GeofenceTransitionsIntentService.class);
    // We use FLAG_UPDATE_CURRENT so that we get the same pending intent
    // back when calling addgeoFences()
    return PendingIntent.getService(moContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

GeofenceTransitionsIntentService.class

import java.util.ArrayList;
import java.util.List;
import com.google.android.gms.location.Geofence;
import com.google.android.gms.location.GeofenceStatusCodes;
import com.google.android.gms.location.GeofencingEvent;
import android.R.bool;
import android.app.IntentService;
import android.app.usage.UsageEvents.Event;
import android.content.Intent;
import android.database.Cursor;
import android.location.Location;
import android.text.TextUtils;

public class GeofenceTransitionsIntentService extends IntentService {

protected static final String TAG = "GeofenceTransitionsIS";

public GeofenceTransitionsIntentService() {
    super(TAG); // use TAG to name the IntentService worker thread
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
}

private static String getGeofenceTransitionDetails(GeofencingEvent event) {
    String transitionString = GeofenceStatusCodes.getStatusCodeString(event.getGeofenceTransition());
    List<String> triggeringIDs = new ArrayList<String>();
    for (Geofence geofence : event.getTriggeringGeofences()) {
        triggeringIDs.add(geofence.getRequestId());
    }
    return String.format("%s: %s", transitionString, TextUtils.join(", ", triggeringIDs));
}

@Override
protected void onHandleIntent(Intent intent) {

    GeofencingEvent event = GeofencingEvent.fromIntent(intent);
    Log.i(TAG, "Geofencing Event : " + event);
    if (event.hasError()) {
        Log.i(TAG, "GeofencingEvent Error : " + event.getErrorCode());
        return;
    }

    // Get the type of transition (entry or exit)
    if (event.getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_ENTER) {
        Log.i(TAG, "GeofencingEvent Enter");
    }
    if (event.getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_EXIT) {
        Log.i(TAG, "GeofencingEvent Exit");
    ?
    String description = getGeofenceTransitionDetails(event);
    Log.i(TAG, "GeofencingEvent description : " + description);
}

}

Permissions

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.hardware.location.gps" />

i stuck in this issue since many days, please help to finish the issue.


Solution

  • Found one patch to avoid unwanted or dummy events.

    you can get location on trigger time

    Location loTriggerGeoFenceLocation = moEvent.getTriggeringLocation();
    long ldAccuracy = loTriggerGeoFenceLocation.getAccuracy();
    

    now store your geo fence location lat long and radius. not get trigger lat long and check the distance between trigger location and geo fence location lat long. if the distance are less then radius it should be the enter and is distance is more then radius it should be exit event

     if (event.getGeofenceTransition() == Geofence.GEOFENCE_TRANSITION_EXIT) {
    
        ldGeoLatLong = moSharedPreferenceManager.getGeoFenceTimeLocation();
        Location loExistGeoFenceLocation = new Location("");
        loExistGeoFenceLocation.setLatitude(ldGeoLatLong[0]);
        loExistGeoFenceLocation.setLongitude(ldGeoLatLong[1]);
    
        String lsRadius = moSharedPreferenceManager.getGeoFenceRadius();
        float lfRadius = Float.parseFloat(lsRadius);
            Log.i(TAG, "GeofencingEvent Exit");
            float lfDistance = loTriggerGeoFenceLocation.distanceTo(loExistGeoFenceLocation);
            if (lfDistance >= lfRadius && ldAccuracy <= 100f) {
                moSharedPreferenceManager.setGeoFenceExit(true);
            }
    }