Creating and Monitoring Geofences example app on github does not work as expected, Geofences in Google Play Services don't seem to work properly.
I have read elsewhere at Stack Overflow, that Reto Meier mentioned at Google IO that the GPS will turn on only if the phone approaches the geofence to conserve battery.
Seems that it does not turn on at all.
Here is the situation:
I have an Emulator with Google APIs (same happens with real phone).
I have the above mentioned app out of the box installed and Geofence added.
I have a KML file that drives me in and out of the Geofence.
Gofence ENTER is not triggered.
Now, just to be sure that KML actually works, I open Google maps. I play KML and I can see the blue "You Are Here" dot nicely moving in and out of Geofence, and the geofences do get triggered.
While Google Maps is up and running, I see GPS indicator in status bar.
So, it seems to me that Goefence only gets triggered if the GPS is explicitly on.
Can somebody explain this please? There is a lot of questions here on Stack Overflow that deal with the same problem.
Thanks.
EDIT:
Did the field test with real phone. While Location Updates app was running and tracking me Creating and Monitoring Geofences example app was getting ENTER/EXIT events. As soon as I killed Location Updates app, the Geofences app stopped getting ENTER/EXIT events.
Seems to me like Google has optimized the power consumption for Geofences to the point of uselessness.
I found the solution. It's an abuse, but that's the only way to get Geofence useful.
All I need to do is request location updates:
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(5000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, mGeofencePendingIntent);
And now we can register geofences.
Here is my understanding why the above works:
According to documentation:
"If your application wants to passively observe location updates triggered by other applications, but not consume any additional power otherwise, then use the PASSIVE_PROVIDER This provider does not actively turn on or modify active location providers"
Seems to me that added geofence is one of PASSIVE_PROVIDERS. That would explain why geofence got triggered when Google Maps was open.
Of course, we could use PRIORITY_BALANCED_POWER_ACCURACY instead of HIGH (~40m accuracy) to preserve some battery and be smart about when we put geofence on and for how long.
Related
I'm starting to develop an app that will stay in background forever and detect when a user is staying in a certain location for a while (and then display a notification to invite the user to open the app to obtain informations about that place).
It's something very similar to what Google Maps does when you're in a restaurant and it shows you a notification to check ratings about it.
What I want is to have a minimal impact on device, so location updates should be very "passive", getting the location only when user is not moving and, if possible, recycling location data that is already got by other activities - maybe by Google Maps itself or other location apps that are running on the devices.
This is not a navigation app, so I don't need to have the live fine location but simply the approximate place with the best accuracy and minimal effort, and only if user is not moving.
LocationListener and onLocationChanged seems to be my men, but can I specify that I don't want to trigger device's sensors and only re-use location data when it's available for other scopes? My app should check these informations and then decide to do a reverse geocode if and when they are accurate enough.
Yes, LocationListener and onLocationChanged are your men, though for a passive implementation, there are a few options you can go through.
First you can check for the last known location, maybe compare it in terms of its time; i.e. getTime() and verify whether it is of use to you.
In terms of code, literally...
Google samples, android location has what is relevant for the last location part:
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) {
// Provides a simple way of getting a device's location and is well suited for
// applications that do not require a fine-grained location and that do not need location
// updates. Gets the best and most recent location currently available, which may be null
// in rare cases when a location is not available.
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Further, you can combine it with LocationRequest object, this helps your implementation as you can call it right after trying getLastLocation() and basically have a more reliable arrangement for obtaining location.
// Create the location request
mLocationRequest = LocationRequest.create()
//priority object needs to be set, the following will definitely get results for you
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
//interval updates can be on the lines of 15mins or 30... acc to your requirement
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
// Request location updates
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
i suggest give PRIORITY_NO_POWER a try, could work well in combination with getLastLocation(). These power modes have been added specifically for optimising battery/power consumption and efficiency for retrieving location.
I'm creating an app which tracks the location through FusedLocationProviderApi in a Foreground Service.
When I create LocationRequest with PRIORITY_BALANCED_POWER_ACCURACY and start listening for location updates, to my surprise GPS fires up ( Location in the phone settings is set to High Accuracy). I get the location almost immediately (through wifi/cell sources I guess), but as I'm indoors I can't get a GPS fix and it just keeps on trying without end...
Even though I didn't ask for PRIORITY_HIGH_ACCURACY I get hit with significant battery drain and get blamed for using GPS for several minutes.
Is there a way to set a timeout for GPS search (detect indoors situation)?
Is it possible to get a decent location using FusedLocationProviderApi without automatically triggering GPS or do I have to revert to the old location API?
Do I have to resort to limiting each LocationRequest to couple of minutes (setExpirationDuration) and create a new one to prevent the GPS battery drain?
[EDIT]: I think I might have found an another culprit. On a map tab in the app I have set setMyLocationEnabled(true), and this seems to be causing the GPS to flare up. I will experiment a bit more and post the results. Still I'm interested in how the location manager decides that enough is enough when it comes to GPS fix attempt.
Thanks in advance!
Ok, I may sound stupid but I am confused in between Location Manager Proxmity alert and Geofence.
Which one of these is a better way to detect if the user has reached a particular location?
An important note on the Google Play GeoFencing API. I've found that the GeoFencing never intelligently retrieves locations from the GPS hardware. The GeoFence API will observe the most accurate location available from the OS or if no recent location reading is available, it will cause a location to be calculated from Wifi / Cellular. (which sucks because cellular is wildly inaccurate and wifi is often unavailable)
So to get at all responsive or accurate results out of the Geofencing API you have to set up your Geofences and then poll the GPS hardware on an interval, not even doing anything with the result received, so that under the surface you are providing worthwhile data to the OS.
I can't speak specifically to the behaviour of LocationManager.addProximityAlert but I doubt it behaves any differently. You could really use either and the results and performance will likely be identical because the heavy lifting is done by waking up the GPS manually.
I am developing an android application wherein I need the user location updates pretty frequently. Say 2 times a minute.
Earlier I had been using Google Play Service's "Fused location service" but the location updates were not received as requested.
The location updates got stuck for sometime, the interval between updates jumped to 10min or so.Sometimes even if I put my priority to "PRIORITY_HIGH_ACCURACY" the same happened.
I then went back to the old "Location Manager" and when I used the "NETWORK_PROVIDER", I noticed that the location updates got stuck due to this provider. Also the GPS does not get activated immediately, it takes some time. I am trying to build my custom fused location provider. How can I efficiently switch between providers, without getting lags on location updates.
I want to know what are the best practices for getting location updates regularly, all the time, be it either NW, GPS or both. Like it should work for an application where location updates getting stuck cannot be afforded.
Battery drain is not an issue for me right now.I am aware of all the supporting docs that Google provides regarding location access.
Any help would be much appreciated.
Thankyou !
FusedLocationProvider really is the best option for obtaining locations at the moment, because it uses a lot more than just GPS or Network data to obtain location fixes. I have experienced issues regarding intervals being missed as well, but ultimately this is something down to luck depending on availability of GPS, Network, etc. etc.
My favourite usage of FusedLocationProvider so far is in conjunction with the AlarmManager class: Basically, the idea is to start location tracking at intervals specified by the Alarm Manager (this can be set to every 30 seconds such as in your case). Once the interval is hit, the location provider is to obtain a location fix as soon as possible (so in the setInterval method or whatever it's called, the parameter is a 0). This way, you can avoid having to wait another 30 seconds for a new location, instead having the location tracker attempt to provide a location as soon as possible after the interval specified by the Alarm Manager is hit.
By the way, when making custom location tracking wrappers, be careful of using the .getLastKnownLocation() method as it only uses cached locations - you could end up sending the same location to the user every 30 seconds.
Good luck!
greetings
I have a ICE Cream sandwitch phone with google play service.
Installed the Geofencedetection sample app from the following
http://developer.android.com/training/location/geofencing.html
I also installed a Mock Location application
Using this mock location i have set my location as new delhi (lat 28.66 long 77.21).
Now i registered the following geofences using the sample app
Geofence1
lat 11.94898
long 79.48475
radius 1000 meters
Geofence2
lat 77.00000
long 77.00000
radius 1000 meters
Now i again opened the mock location and set the
location as (within geofence 1) my home.
lat 11.94898
long 79.48475
I have checked the mock location with the Maps application.
It displays correctly. I enabled the Allow Mock Locations
in Developer options
But the sample Geofence application is not triggering any
notification. I checked the code. As per the code it should send
notification when the user enters the geofence.
I could not understand why it is not sending notification.
Will this work only on real network?
Please let me know if i am doing anything wrong?
Best Regards
jothi
I had a similar experience using the sample MockLocation app from
http://developer.android.com/training/location/location-testing.html
For example if my geofence is set at 5,100 and I use the mocklocation app to inject a single mock location at 5,100, the geofence will not trigger.
However, if you repeatedly inject multiple mock locations at 5,100 the geofence will trigger. In my case, injecting mock locations at 5,100 three times consecutively caused my geofence to trigger. To be clear, when I say inject I mean doing:
mLocationClient.setMockLocation(yourMockLocation);
Everything below is pure speculation on my part so take it with a grain of salt:
My speculation is there is some filtering algorithm in the LocationClient backend whose purpose is to filter out spurious sensor values and it might be detecting that huge change in lat/long as a possible spurious value. Another possibility is the geofence simply doesnt trigger until it receives multiple readings that indicate you are within its vicinity.
Please check notification of app when app in foreground because i am also not getting any update for geofence in background. But in foreground, It is working fine.
I have stuck with this problem for sometime. Then eventually it turns out the google mock location tutorial (http://developer.android.com/training/location/location-testing.html) failed to mention you will need to set below two calls with the mock location you created:
/*
setElapsedRealtimeNanos() was added in API 17
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
newLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
newLocation.setTime(System.currentTimeMillis());
Without these two calls my mock location won't trigger my geofence. After calling these my geofence is triggered without issues.
I also had a similar experience with MockLocation app, just use a large number of seconds on "send interval" field, like 7 seconds, and the geofence will trigger.
After spending a ton of time on this I finally figured out that the secret was to use the provider name "network" when creating the mock location instance.
Location location = new Location("network");