Geofence not triggering
Asked Answered
K

3

6

I'm trying to implement Geofence on my APP and the problem is that is not triggering when I'm on the place that I've marked.

The thing that I do is I set the Latitude & Longitude from a Place Picker.

The values that I'm getting are fine because I put it on google maps and the place is the correct one, because I've read many answers that people was setting bad values from lat/long.

I've two classes : GeofenceSingleton.class and GeofenceTransitionsIntentService.

The GeofenceSingleton.class looks like :

public class GeofenceSingleton implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> {

private GoogleApiClient googleApiClient;
private static GeofenceSingleton _singleInstance;
private static Context appContext;
private static final String ERR_MSG = "Application Context is not set!! " +
        "Please call GeofenceSngleton.init() with proper application context";
private PendingIntent mGeofencePendingIntent;
private static ArrayList<Geofence> mGeofenceList;


private GeofenceSingleton() {
    if (appContext == null)
        throw new IllegalStateException(ERR_MSG);

    this.googleApiClient = new GoogleApiClient.Builder(this.appContext)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    this.googleApiClient.connect();
    mGeofenceList = new ArrayList<Geofence>();
}

/**
 * @param applicationContext
 */
public static void init(Context applicationContext) {
    appContext = applicationContext;
}

public static GeofenceSingleton getInstance() {
    if (_singleInstance == null)
        synchronized (GeofenceSingleton.class) {
            if (_singleInstance == null)
                _singleInstance = new GeofenceSingleton();
        }
    return _singleInstance;
}

@Override
public void onConnected(Bundle bundle) {

}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}

public void addGeofence(Location location, String uid) {
    mGeofenceList.add(new Geofence.Builder()
            .setRequestId(uid)
            .setCircularRegion(
                    location.getLatitude(),
                    location.getLongitude(),
                    500
            )
            .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
            .setExpirationDuration(1000000)
            .build());
}

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

private PendingIntent getGeofencePendingIntent() {
     // Reuse the PendingIntent if we already have it.
    if (mGeofencePendingIntent != null) {
        return mGeofencePendingIntent;
    }
    Intent intent = new Intent(appContext, GeofenceSingleton.class);
    // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
    // addGeofences() and removeGeofences().
    return PendingIntent.getService(appContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

public void startGeofencing() {
    if (!googleApiClient.isConnected()) {
        Toast.makeText(appContext, "API client not connected", Toast.LENGTH_SHORT).show();
        return;
    }

    LocationServices.GeofencingApi.addGeofences(
            googleApiClient,
     // The GeofenceRequest object.
            getGeofencingRequest(),
    // A pending intent that that is reused when calling removeGeofences(). This
    // pending intent is used to generate an intent when a matched geofence
    // transition is observed.
            getGeofencePendingIntent()
    ).setResultCallback(this); // Result processed in onResult().
    Toast.makeText(appContext,"Geofencing started", Toast.LENGTH_LONG).show();
}



public void removeGeofence(){
    LocationServices.GeofencingApi.removeGeofences(
            googleApiClient,
// This is the same pending intent that was used in addGeofences().
            getGeofencePendingIntent()
    );
}

@Override
public void onResult(Status status) {
    if (status.isSuccess()) {
// Update state and save in shared preferences.

        Toast.makeText(
                appContext,
                "YO",
                Toast.LENGTH_SHORT
        ).show();
    } else {
        Toast.makeText(
                appContext,
                "NOO",
                Toast.LENGTH_SHORT
        ).show();
    }
}
}

And GeofenceTransitionsIntentService

public class GeofenceTransitionsIntentService extends IntentService {

private static final String TAG = "Geofence-Service";
private Handler handler;
SharedPreferences sp;
SharedPreferences.Editor editor;
String EmailName, MessageEmail;
Context mContext;
Boolean EmailSent = false;

public GeofenceTransitionsIntentService() {
    super(TAG);
}

@Override
public void onCreate() {
    super.onCreate();
    this.mContext = this;
    sp = PreferenceManager.getDefaultSharedPreferences(this);
    handler = new Handler();
}

@Override
protected void onHandleIntent(Intent intent) {

    final GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
    if (geofencingEvent.hasError()) {
        Log.e(TAG, "Error in geofencing event");
        return;
    }

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

      // Test that the reported transition was of interest.
    if (geofenceTransition == 1) {

        handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(), "Entered", Toast.LENGTH_SHORT).show();
                sendNotification();
            }
        });
        Log.i(TAG, "Entered");


    }

    else {
        // Log the error.
        handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(), "Sorry you are out", Toast.LENGTH_SHORT).show();
            }
        });
        Log.e(TAG, String.valueOf(geofenceTransition));
    }

}

private void sendNotification() {
    Toast.makeText(GeofenceTransitionsIntentService.this, "HEEEEEEEY I'M IN", Toast.LENGTH_SHORT).show();



}

On my MainActivity I've got this :

GeofenceSingleton.init(this); //If I don't call this the class doesn't work
this.geofenceSingleton = GeofenceSingleton.getInstance();

And then I build a Geofence as follows :

Location geofence = new Location("");
geofence.setLatitude(Double.parseDouble(latitude));
geofence.setLongitude(Double.parseDouble(longitude));
geofenceSingleton.addGeofence(geofence, GeofenceKey);
geofenceSingleton.startGeofencing();

NOTES

I've added <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> on my manifest.xml

I declared the service as <service android:name=".GeofenceTransitionsIntentService"/>

And I added this line on my build.gradle : compile 'com.google.android.gms:play-services:7.8.0'

It only shows Toast.makeText(appContext,"YO",Toast.LENGTH_SHORT).show(); that's because status is success, and also shows the Toast.makeText(appContext,"Geofencing started", Toast.LENGTH_LONG).show(); means that it's started.

QUESTION

Why my IntentService is never called?

I tested it putting a Lat/Long of my home and since I'm on it should be triggered, isn't it?

Katherinkatherina answered 4/10, 2015 at 19:30 Comment(2)
did it work?, btw I created a new project with these 3 files and then tried to do it and it works, so I would work for you too.Adjunction
Maybe you are not "entering" the zone and that's why there's no event. You are just inside when the geofence is created. In order to trigger it when you create the zone AND you are already inside you need to set it this way: builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);Autosome
A
6

It will never work because what you are doing is

Intent intent = new Intent(appContext, GeofenceSingleton.class);

passing intent to GeofenceSingleton ?

What you need to do is

Intent intent = new Intent(appContext, GeofenceTransitionsIntentService.class);
Adjunction answered 4/10, 2015 at 21:8 Comment(3)
@Skizo-ozᴉʞS I am able to get ENTER NOTIFICATION but EXIT NOTIFICATION is not getting FIREDTosspot
@Skizo-ozᴉʞS Also When I give the radius less than 25 meters I am not getting ENTER NOTIFICATION any idea why it is not working ???Tosspot
exit notification is not fired as you have setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER) You need to add GEOFENCE_TRANSITION_ENTER as well in order to get the exit transitionTerisateriyaki
N
0

If your Intent is already constructed with the proper class (see varunkr's answer), you also need to make sure the service is also included in your AndroidManifest.xml.

<application
    ...

    <service android:name=".GeofencingTransitionIntentService" />
Nada answered 4/9, 2018 at 17:16 Comment(0)
T
0

Make sure your service and broadcast receive have these property enabled in manifest.

  android:enabled="true"
  android:exported="true"
Tangram answered 7/10, 2018 at 9:3 Comment(1)
doesn't it need a permission assigned is you export it?Celik

© 2022 - 2024 — McMap. All rights reserved.