I am using an intent to switch to Google Maps to get the route to a marker that's shown on a map that's implemented in my app. My question is if there is any way to let my app in background to send the location at certain intervals of time, so when the user gets close to the location, when the app is reopened to have the location updated directly, so I would be able to implement the next step of the app.( the app should do something when he is close)
You can try create and monitor geofence for detect user gets close to the location:
public class MainActivity extends AppCompatActivity {
// ...
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (geofencePendingIntent != null) {
return geofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
geofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
return geofencePendingIntent;
}
and then, when user gets close to the location start tracking it directly from your app. Something like that:
public class GeofenceBroadcastReceiver extends BroadcastReceiver {
// ...
protected void onReceive(Context context, Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceStatusCodes.getErrorString(geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER) {
// Get the geofences that were triggered. A single event can trigger
// multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(
this,
geofenceTransition,
triggeringGeofences
);
// Start tracking user position directly here
...
} else if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Stop tracking user position directly here
...
else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
geofenceTransition));
}
}
}
I'm not sure it will work or not but you can try this one. my guess should work.
ActivityManager activityManager = (ActivityManager) getApplicationContext()
.getSystemService(Context.ACTIVITY_SERVICE);
activityManager.moveTaskToFront(getTaskId(), 0);
Please note that you cannot keep to get the user location in the background when the system is greater than or equal to android O
Background Execution Limits
Solution : You can register a Service in the foreground.
Step 1:Create your own service
Step 2:register with Androidmanifest
Step 3:Create BroadcastReceiver receiver data
Step 4:In onResume bind and onstop unbind service
foreground example from google
Related
I have a requirement where I want to get the user's current location and based on the user's current location I want to get other user's information from app server and want to show them in a list. Users should be within 5 or 10 km radius.
I fetched users data from server showing it in the app but I want to show within that particular radius. Any help is appreciable.
You need to use Geofences, Please follow the below steps you definitely get the result as you want.
Let's see how it's work.
Geofencing combines awareness of the user's current location with awareness of the user's proximity to locations that may be of interest. To mark a location of interest, you specify its latitude and longitude. To adjust the proximity for the location, you add a radius. The latitude, longitude, and radius define a geofence, creating a circular area, or fence, around the location of interest.
You can have multiple active geofences, with a limit of 100 per device user.
Now, let's see how we use it in our application,
Set up for Geofence Monitoring
The first step in requesting geofence monitoring is to request the necessary permission. To use geofencing, your app must request ACCESS_FINE_LOCATION. To request this permission, add the following element as a child element of the <manifest> element in your app manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
If you want to use an IntentService to listen for geofence transitions, add an element specifying the service name. This element must be a child of the <application> element:
<application
android:allowBackup="true">
...
<service android:name=".GeofenceTransitionsIntentService"/>
<application/>
To access the location APIs, you need to create an instance of the Geofencing client. To learn how to connect your client:
private GeofencingClient mGeofencingClient;
// ...
mGeofencingClient = LocationServices.getGeofencingClient(this);
Create and Add Geofences
Note: On single-user devices, there is a limit of 100 geofences per
app. For multi-user devices, the limit is 100 geofences per app per
device user.
Create geofence objects
First, use Geofence.Builder to create a geofence, setting the desired radius, duration, and transition types for the geofence. For example, to populate a list object named mGeofenceList:
mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId(entry.getKey())
.setCircularRegion(
entry.getValue().latitude,
entry.getValue().longitude,
Constants.GEOFENCE_RADIUS_IN_METERS
)
.setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
Geofence.GEOFENCE_TRANSITION_EXIT)
.build());
Specify geofences and initial triggers
The following snippet uses the GeofencingRequest class and its nested GeofencingRequestBuilder class to specify the geofences to monitor and to set how related geofence events are triggered:
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeofenceList);
return builder.build();
}
Define an Intent for geofence transitions
The Intent sent from Location Services can trigger various actions in your app, but you should not have it start an activity or fragment, because components should only become visible in response to a user action. In many cases, an IntentService is a good way to handle the intent. An IntentService can post a notification, do long-running background work, send intents to other services, or send a broadcast intent. The following snippet shows how to define a PendingIntent that starts an IntentService:
public class MainActivity extends AppCompatActivity {
// ...
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
Add geofences
To add geofences, use the GeofencingClient.addGeofences() method. Provide the GeofencingRequest object, and the PendingIntent. The following snippet demonstrates processing the results:
mGeofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent())
.addOnSuccessListener(this, new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// Geofences added
// ...
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Failed to add geofences
// ...
}
});
Handle Geofence Transitions
Note: On Android 8.0 (API level 26) and higher, if an app is running in the background while monitoring a geofence, then the device
responds to geofencing events every couple of minutes. To learn how to
adapt your app to these response limits, see Background Location
Limits.
public class GeofenceTransitionsIntentService extends IntentService {
// ...
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofences that were triggered. A single event can trigger
// multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(
this,
geofenceTransition,
triggeringGeofences
);
// Send notification and log the transition details.
sendNotification(geofenceTransitionDetails);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
geofenceTransition));
}
}
Stop Geofence Monitoring
mGeofencingClient.removeGeofences(getGeofencePendingIntent())
.addOnSuccessListener(this, new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
// Geofences removed
// ...
}
})
.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
// Failed to remove geofences
// ...
}
});
you should implement logic on server based on the latitude and longitude and return the data
my Android app functionally is added current location and image in app using google mapv2 image and address store in server . now I want to alert when you reach in 100 meter in your added location in app. can you help me. thanks
You need to create and monitor geofences.
Create a geofence list:
First, use Geofence.Builder to create a geofence, setting the desired radius, duration, and transition types for the geofence. For example, to populate a list object named mGeofenceList:
mGeofenceList.add(new Geofence.Builder()
// Set the request ID of the geofence. This is a string to identify this
// geofence.
.setRequestId(entry.getKey())
.setCircularRegion(
entry.getValue().latitude,
entry.getValue().longitude,
Constants.GEOFENCE_RADIUS_IN_METERS
)
.setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER |
Geofence.GEOFENCE_TRANSITION_EXIT)
.build());
Specify geofences and initial triggers:
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeofenceList);
return builder.build();
}
Define an Intent for geofence transitions:
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
return PendingIntent.getService(this, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
Add geofences:
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(this);
Handle Geofence Transitions:
GeofenceTransitionsIntentService obtains the geofencing event from the intent, determines the type of Geofence transition(s), and determines which of the defined geofences was triggered. It then sends a notification as the output.
public class GeofenceTransitionsIntentService extends IntentService {
...
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = GeofenceErrorMessages.getErrorString(this,
geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofences that were triggered. A single event can trigger
// multiple geofences.
List triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(
this,
geofenceTransition,
triggeringGeofences
);
// Send notification and log the transition details.
sendNotification(geofenceTransitionDetails);
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
geofenceTransition));
}
}
Checkout this official document for Creating and Monitoring Geofences to get detailed information about it.
Its very simple. You implement the Localistener class and use the distanceTo function there to check the distance and then use notificationmanager. I actually cannot understand the question properly .Do you only want the location distance or something else... Can you tell clearly?
I followed this developer tutorial, and have Geofencing working within my app, as expected.
A notification is sent when a Geofence Transition occurs, from within an IntentService:
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
...
sendNotification(geofenceTransitionDetails);
}
private void sendNotification(String notificationDetails) {
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(MainActivity.class);
// Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Define the notification settings.
builder.setSmallIcon(R.mipmap.ic_launcher)
// In a real app, you may want to use a library like Volley
// to decode the Bitmap.
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setColor(Color.RED)
.setContentTitle(notificationDetails)
.setContentText("Return to app")
.setContentIntent(notificationPendingIntent);
// Dismiss notification once the user touches it.
builder.setAutoCancel(true);
// Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
This is cookie-cutter from the tutorial. The intent is set-up in the Main activity:
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
// addGeofences() and removeGeofences().
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
How can I add functionality that suppresses the notifications if the app is open, and instead displays an AlertDialog to the user? Ideally, I'd like to be able to execute different tasks, depending on which view the user is currently in when the Geofence Transition occurs. Can I monitor/intercept the transition from within each view, or somehow globally?
Thanks in advance.
Some of the answers were incomplete, and so here is the complete solution to what I was looking for.
First off, set up MyApplication class, that implements ActivityLifecycleCallbacks:
public class MyApplication extends Application implements Application.ActivityLifecycleCallbacks {
private static boolean isActive;
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(this);
}
public static boolean isActivityVisible(){
return isActive;
}
#Override
public void onActivityResumed(Activity activity) {
isActive = true;
}
#Override
public void onActivityPaused(Activity activity) {
isActive = false;
}
... no other methods need to be used, but there are more that
... must be included for the ActivityLifecycleCallbacks
}
Be sure to name this in your manifest (only name line was added, rest is default):
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:hardwareAccelerated="true">
What was done above is used to track the lifecycle of your app. You can use this to check if your app is currently in the foreground or not.
Next is to set up a BroadcastReceiver, wherever you would like code to run (in the event that the app is open when the trigger occurs). In this case, it is in my MainActivity:
protected BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
... Do whatever you want here
Toast.makeText(...).show();
}
};
Register the receiver in your onCreate of the same activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
LocalBroadcastManager.getInstance(this).registerReceiver(mNotificationReceiver, new IntentFilter("some_custom_id"));
}
And don't forget to unregister it:
#Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mNotificationReceiver);
super.onDestroy();
}
When a broadcast is received, the code within the receiver is executed.
Now, to check if the app is in the foreground, and send a broadcast if it is. Inside of the IntentService:
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = getErrorString(this,
geofencingEvent.getErrorCode());
return;
}
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
...
if(MyApplication.isActivityVisible()){
Intent intnt = new Intent("some_custom_id");
intnt.putExtra("message", geofenceTransitionDetails);
LocalBroadcastManager.getInstance(this).sendBroadcast(intnt);
}else{
sendNotification(geofenceTransitionDetails);
}
} else {
// Log the error.
}
}
The important bit is the last nested if-statement:
if(MyApplication.isActivityVisible()){
Intent intnt = new Intent("some_custom_id");
intnt.putExtra("message", geofenceTransitionDetails);
LocalBroadcastManager.getInstance(this).sendBroadcast(intnt);
}else{
sendNotification(geofenceTransitionDetails);
}
Check if the app is in the foreground using MyApplication.isActivityVisible(), as defined above, and then either send the notification, or send a broadcast. Just make sure that your intent code (i.e. "some_custom_id") matches on your sender and receiver.
And that's about it. If the app is in the foreground (specifically the MainActivity), I execute some code. If the app is not in the foreground, I send a notification.
The easiest way would be to use LocalBroadcastManager or some event bus.
So when transition happens you should send local broadcast from IntentService and catch it with some component X in between IntentService and any of your Activity's. Component X must track if any of your Activity's is in foreground and
if yes - pass other local broadcast up (to the foreground Activity),
if not - show notification.
Please note that in Android you cannot track easily if your app is in foreground or not (and if you have more than 1 Activity, you cannot do it properly in my opinion) but you can try.
a) You can notify your service of the activity's lifecycle events.
b) You can keep the current state of your UI in a static field in the activity and check it from the service before showing the notification.
I use Geofences in my app, everything works fine except the removal of triggered geofences.
I red the guide from the official documentation of Android but they don't explain how to remove a geofence inside of the IntentService.
Here is the code of the event handler of the service:
#Override
protected void onHandleIntent(Intent intent)
{
Log.e("GeofenceIntentService", "Location handled");
if (LocationClient.hasError(intent))
{
int errorCode = LocationClient.getErrorCode(intent);
Log.e("GeofenceIntentService", "Location Services error: " + Integer.toString(errorCode));
}
else
{
int transitionType = LocationClient.getGeofenceTransition(intent);
if (transitionType == Geofence.GEOFENCE_TRANSITION_ENTER)
{
List <Geofence> triggerList = LocationClient.getTriggeringGeofences(intent);
String[] triggerIds = new String[triggerList.size()];
for (int i = 0; i < triggerIds.length; i++)
{
// Store the Id of each geofence
triggerIds[i] = triggerList.get(i).getRequestId();
Picture p = PicturesManager.getById(triggerIds[i], getApplicationContext());
/* ... do a lot of work here ... */
}
}
else
Log.e("ReceiveTransitionsIntentService", "Geofence transition error: " + Integer.toString(transitionType));
}
}
How can I delete the geofence after he got triggered ?
You can do something like this:
LocationServices.GeofencingApi.removeGeofences(
mGoogleApiClient,
// This is the same pending intent that was used in addGeofences().
getGeofencePendingIntent()
).setResultCallback(this); // Result processed in onResult().
And your getGeofencePendingIntent() method can look like this:
/**
* Gets a PendingIntent to send with the request to add or remove Geofences. Location Services
* issues the Intent inside this PendingIntent whenever a geofence transition occurs for the
* current list of geofences.
*
* #return A PendingIntent for the IntentService that handles geofence transitions.
*/
private PendingIntent getGeofencePendingIntent() {
Log.d(TAG, "getGeofencePendingIntent()");
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(mContext, GeofenceIntentServiceStub.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
// addGeofences() and removeGeofences().
mGeofencePendingIntent = PendingIntent.getService(mContext, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
You would proceed as you did when adding Geofences (create a LocationClient and wait for it to connect). Once it is connected, in the onConnected callback method, you would call removeGeofences on the LocationClient instance instead and pass it a list of request IDs you want to remove and an instance of OnRemoveGeofencesResultListener as a callback handler.
Of course, you must use the same request IDs you used when creating the GeoFence with GeoFence.Builder's setRequestId.
#Override
public void onConnected(Bundle arg0) {
locationClient.removeGeofences(requestIDsList,
new OnRemoveGeofencesResultListener() {
...
});
I'm trying to implement a Geofencing mechanism where a geofence is monitored and once the user exits the current geofence, the current co-ordinates are used to create a new geofence and db query is initiated for fetching some data.
My problem is that the pending intent is never fired.
From the logs i can see that the geofences are being added into the location client. However no pending intents are fired upon location change.(i've set the fence radius at 2m and i've walked over 100mts). Is there something wrong in the way i've declared the intent service ?
Here is the intent service class.
public class GeoFenceIntentService extends IntentService{
private static final String mIntentName = "GeoFenceIntentService";
public GeoFenceIntentService() {
super(mIntentName);
}
#Override
protected void onHandleIntent(Intent intent) {
int transitionType = LocationClient.getGeofenceTransition(intent);
Log.e(TAG,"Inside fence handler");
if(transitionType == Geofence.GEOFENCE_TRANSITION_EXIT){
//Query DB here with current co-ords
//create new GeoFence
Location location = LocationHelper.getInstance(mContext).getLastLocation();
mLat = String.valueOf(location.getLatitude());
mLong = String.valueOf(location.getLongitude());
addGeofenceToMonitor(location);
queryDb();
}
}
}
Also here is where i add the pending intents and the geofence to the location client
addGeofenceToMonitor(Location location){
List<Geofence> list = new ArrayList<Geofence>();
list.add(getNewGeofence(location.getLatitude(), location.getLongitude()));
PendingIntent pendingIntent = PendingIntent.getService(mContext, 0,
new Intent(mContext,GeoFenceIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
OnRemoveGeofencesResultListener removeListener = new OnRemoveGeofencesResultListener() {
#Override
public void onRemoveGeofencesByRequestIdsResult(int statusCode, String[] requestIDs) {
//To be used
}
#Override
public void onRemoveGeofencesByPendingIntentResult(int statusCode,PendingIntent pendingIntent) {
//Not used
}
};
LocationHelper.getInstance(mContext).removeGeoFence(mGeofenceRequestIDs, removeListener);
OnAddGeofencesResultListener addListener = new OnAddGeofencesResultListener() {
#Override
public void onAddGeofencesResult(int statusCode, String[] geofenceRequestIds) {
if(statusCode != LocationStatusCodes.SUCCESS){
//handle error cases
}
else
Log.i(TAG, "Successfully added Geofence "+geofenceRequestIds[0]+" for monitoring");
}
};
LocationHelper.getInstance(mContext).addGeoFence(list, pendingIntent, addListener);
}
Here is the snippet from the manifest file
<service
android:name="com.myexample.sample.GeoFenceIntentService"
android:label="#string/app_name"
android:exported="true">
</service>
Read this.
Have you checked the position estimation circle you are getting? You can use mock locations app to set the position as well as the accuracy circle. Your geofence may be too small to accommodate your position circle and that is why the events are not triggered.
Android GeoFences never enable the GPS (because their API is awful and their device power consumption is already so out of hand). You have to set up your geofences and then constantly poll the GPS separately if you want geofencing over GPS.
The handler of the GPS polling can be null, the poll only exists to force accurate information into their awful location API and in turn trigger the fences.