GEOFENCE TRANSITION DWELL not working in android

3.1k views Asked by At

I am working on geofence, I have problem related to GEOFENCE TRANSITION DWELL not Trigger while Enter and Exit Transition working fine. I spent lots of time of time googling but find too much about my problem. I just want to send notification after every one minute to user If user stay within geofence radius.

Here is my Geofence Helper Class:

public class GeofenceHelper {

private Context mContext;
private GeofencingRequest geoFencingRequest;
private Intent intent;
private PendingIntent pendintIntent;

public GeofenceHelper(Context mContext) {
    this.mContext = mContext;
}

public void addGeofence(List<ExcelDataModel> excelDataModel, ResultCallback<Status> statusResultCallback) {
    List<Geofence> geofenceList = new ArrayList<>();
    for (ExcelDataModel dataModel : excelDataModel) {
        if (!TextUtils.isEmpty(dataModel.getLatitude()) && !TextUtils.isEmpty(dataModel.getLongitude()) && !TextUtils.isEmpty(dataModel.getRadius())) {
            Geofence geofence = new Geofence.Builder()
                    .setRequestId(String.valueOf(dataModel.getId()))
                    .setCircularRegion(Double.parseDouble(dataModel.getLatitude()), Double.parseDouble(dataModel.getLongitude()), Float.parseFloat(dataModel.getRadius()))
                    .setExpirationDuration(Geofence.NEVER_EXPIRE)
                    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT | Geofence.GEOFENCE_TRANSITION_DWELL)
                    .setLoiteringDelay(60000)
                    .build();

            geofenceList.add(geofence);
        }
    }

    if (geofenceList.size() < 1){
        Toast.makeText(mContext, "NO valid geofence.", Toast.LENGTH_SHORT).show();
        return;
    }

    geoFencingRequest = new GeofencingRequest.Builder()
            .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
            .addGeofences(geofenceList)
            .build();


    intent = new Intent(mContext, GeofenceService.class);
    intent.putExtra(GeofenceService.EXTRA_ID, 12);
    pendintIntent = PendingIntent.getService(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    LocationServices.GeofencingApi
            .addGeofences(App.getGoogleApiHelper().googleApiClient, geoFencingRequest, pendintIntent)
            .setResultCallback(statusResultCallback);

    Toast.makeText(mContext, "Total Geofences: " + geofenceList.size(), Toast.LENGTH_SHORT).show();

}
}

And Here is my Geofence Service Class:

public class GeofenceService extends IntentService {

public static final String TAG = GeofenceService.class.getSimpleName();
public static String EXTRA_ID = "extra_id";


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return super.onStartCommand(intent, flags, startId);
}

public GeofenceService() {
    super(TAG);
}

@Override
protected void onHandleIntent(Intent intent) {
    GeofencingEvent event = GeofencingEvent.fromIntent(intent);
    if (event.hasError()) {
        Toast.makeText(this, "Goefence Error: " + event.getErrorCode(), Toast.LENGTH_SHORT).show();
    } else {
        int transition = event.getGeofenceTransition();
        Log.d(TAG, "onHandleIntent: " + transition);
        List<Geofence> geofences = event.getTriggeringGeofences();

        Geofence geofence = geofences.get(0);
        String requestId = geofence.getRequestId();

        ExcelDataModel excelData = App.getDatabaseAdapter().getRecordById(requestId);
        CategoryModel categoryModel = App.getDatabaseAdapter().getCategoryById(excelData.getCategory());

        if (transition == Geofence.GEOFENCE_TRANSITION_ENTER) {

            if (categoryModel.getStatus() == 1){

                sendNotification(excelData.getName(),excelData.getNotificationMessage());
            }
            App.getDatabaseAdapter().addOrUpdateNOtificaion(new NotificationModel(requestId, excelData.getName(), excelData.getNotificationMessage(), getDateTime()));

        }else if (transition == Geofence.GEOFENCE_TRANSITION_EXIT){

            if (categoryModel.getStatus() == 1) {
                sendNotification(excelData.getName(), "Exit Geofence");
            }

            App.getDatabaseAdapter().addOrUpdateNOtificaion(new NotificationModel(requestId, excelData.getName(), excelData.getNotificationMessage(), getDateTime()));
        } else if (transition == Geofence.GEOFENCE_TRANSITION_DWELL) {
            Log.d(TAG, "DWELL geofence- " + requestId);
            if(categoryModel.getStatus() == 1) {
                sendNotification(excelData.getName(), "Hello buddy You are still here!!");
            }

            App.getDatabaseAdapter().addOrUpdateNOtificaion(new NotificationModel(requestId, excelData.getName(), excelData.getNotificationMessage(), getDateTime()));

        }
    }
}

public void sendNotification(String title, String mess) {

    Intent ii = new Intent(this, MainActivity.class);
    ii.putExtra("check",R.id.notification_id);
    PendingIntent pi = PendingIntent.getActivity(this, 0, ii, PendingIntent.FLAG_UPDATE_CURRENT);

    NotificationCompat.Builder ncompat = new NotificationCompat.Builder(this)
            .setSmallIcon(R.drawable.ic_notifications_active_black_24dp)
            .setContentTitle(title)
            .setContentText(mess)
            .setContentIntent(pi)
            .setDefaults(Notification.DEFAULT_VIBRATE)
            .setAutoCancel(true);
    Notification notification = ncompat.build();
    NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    nm.notify(0, notification);
}
2

There are 2 answers

1
Alvi On

You need to set initial trigger for dwell along with enter.
Add

GeofencingRequest.INITIAL_TRIGGER_DWELL

in your geoFencingRequest.

    geoFencingRequest = new GeofencingRequest.Builder()
        .setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER|GeofencingRequest.INITIAL_TRIGGER_DWELL)
        .addGeofences(geofenceList)
        .build();

NOTE: Geofence.GEOFENCE_TRANSITION_DWELL is only called when you entered a geofence and stay inside for the time you set in your setLoiteringDelay(timedelay) method in your case dwell will be triggered after 60 seconds you enter a geofence.

0
itamargs On

In case someone still encountering this issue.

There is a misleading snippet in google geofence documentation If you use the snippets for activating geofence notification with broadcast receiver,

You need to make sure that transition of interest includes:

geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL

// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
    geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT ||
    geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL ) {
    ...

The snippet in the documentation isn't contain the DWELL option.

The geofence builder for the DWELL option should look somewhat like this:

geofenceList.add(new Geofence.Builder()
        .setRequestId("geofence1")
        .setCircularRegion(
                latitude, //lat
                longitude, //lon
                radius // radius
        )
        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_DWELL)
        .setLoiteringDelay(10000) //10 seconds for staying in geofence
        .setExpirationDuration(Geofence.NEVER_EXPIRE)
        .build()); 

Works perfectly for me.