I am trying to make an accurate location based app but I am a little bit confused on how the requestlocationupdates works.
If I put the requestlocationUpdates(LocationManager.GPS_PROVIDER, , ); as a location provider and I test my app. I see that if I haven't enabled the gps it takes updates from the network and when its enabled it takes it from the gps. What is the point of setting both network and gps providers to send updates if they switch on their own?
How does the third parameter of requestlocationUpdates work? I mean it says that it changes in the distance that I set but how it can detects that I have moved?
You can try with following code
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
where Criteria is a class indicating the application criteria for selecting a location provider. Providers maybe ordered according to accuracy, power usage, ability to report altitude, speed, and bearing, and monetary cost.
then
locationManager.requestLocationUpdates(provider,0, 0, new MyLocationListener());
Where second and third parameter are use to so that you can control the frequency at which your listener receives updates with the second and third parameter—the second is the minimum time interval between notifications and the third is the minimum change in distance between notifications—setting both to zero requests location notifications as frequently as possible.
keep in mind, once you requestLocationUpdates(...) means onLocationChanged(...) will be triggered when provider specified is enabled and you will get the latest coordinate in onLocationChanged method. There is a default location aka Cache location, or LastKnownLocation which that system will be use before detecting any new location.
Of course system will treated that you're moving when your current location is different than your previous location (cache location).
Related
I want to get 5 consecutive update locations in order to check if the user is moving and to make sure the GPS is calibrated. I did the following:
I added android.permission.ACCESS_FINE_LOCATION" to the manifest and in onConnected:
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(1000); // Update location every second
mLocationRequest.setFastestInterval(1000);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
and in onLocationChanged I did the following:
locationRetries++;
switch (locationRetries) {
case 1: {
firstLatitude = location.getLatitude();
firstLongitude = location.getLongitude();
}
case 5: {
locationRetries = 0;
lastLatitude = location.getLatitude();
lastLongitude = location.getLongitude();
accuracy = Math.round(location.getAccuracy());
stopLocationUpdates();//will remove from location updates and disconnects
float[] results = new float[1];
Location.distanceBetween(firstLatitude, firstLongitude, lastLatitude, lastLongitude, results);
if (results[0] > 5)... //if moved at least 5meters, show popup that the user is moving else do your thing
}
Now I have 3 issues:
1) It seems to take much less than 5 seconds to retrieve the 5 updates even though I set both parameters to be 1000 milliseconds.
2) All the 5 locations (at least the first and last ones) are the same exact location even though I was walking fast. I thought I maybe moving too slow so
3) I closed my app, reopened it on a far location and pressed the button. Almost instantly I got the previous location. I pressed the button again and then I got the real location I was on. It's as if it didn't really asked/waited for a location from the GPS but instead took the last one which was remotely inaccurate at the time. I don't have any "get last known location" code.
I guess the bottom line would be: how can I make sure that it really asks the GPS where am I when I asked for the location and also when asking it for 5 consecutive times, to give me the real locations and not from the cache(?).
The Fused Location Provider
intelligently manages the underlying location technology and gives you the best location according to your needs.
Simple APIs: Lets you specify high-level needs like "high accuracy" or "low power", instead of having to worry about location providers.
Immediately available: Gives your apps immediate access to the best, most recent location.
Power-efficiency: Minimizes your app's use of power. Based on all incoming location requests and available sensors, fused location provider chooses the most efficient way to meet those needs.
Versatility: Meets a wide range of needs, from foreground uses that need highly accurate location to background uses that need periodic location updates with negligible power impact.
There is no guarantee that the fused location provider will ever use GPS - if it has a recent location of the accuracy you request it will return until a better location is returned (i.e., live GPS is returning accurate locations). This ensures that you'll get a better location sooner without waiting for GPS to be primed.
If you specifically need data from GPS, you need to use the LocationManager using the GPS_PROVIDER.
If you are trying to determine what the user is currently doing, you can instead use the ActivityRecognitionApi, which returns DetectedActivity such as WALKING or STILL: using that would give a faster method to understand what the user is currently doing.
I have a background thread that needs to get the GPS location every 1 hour.
What would be the best way to do this?
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000*60*60,0, this);
have the thread sleep for a hour and then register for updates and after receiving the location will
removeUpdates(...)
And what is the difference between LocationManager.NETWORK_PROVIDER and LocationManager.GPS_PROVIDER.
Instead of using LocationManager use Location API . It provides much better accuracy and eats less power and its faster at getting the location.
Your second option from point of GPS consumption is the best one. But instead letting the thread to sleep for an hour I would use a timer with period = 1 hour. If you cannot garuantee that your app will stay active for that hour, you want to store the last reveived location time. Once your app wakes up next time you check the system time stamp and compare it to your last location time on permanent storage. If the hour was exceeded you immeadetly demand a location, and later continue with timers. If the hour has not yet passed, the you calculate the time difference and start a timer with initial delay of that difference, and period of 1hour.
But thi sanswr is not dealing how to keep your app alive, it tells you from point of power consumption that is is better to enable GPS only for that short moment you need it.
Getting a GPS location will need from 20-40s.
You should set highest accuracy. (GPS)
After enabling GPS and receiving a valid location, check the horicontal accuracy.
Leave GPS enabled until the accuracy reach the desired threshold (e.g <15m).
Then disable GPS.
With that solution GPS needs only power for about a minute every hour, which is negligible low.
You can use Criteria for that, customize it according to your need.
A class indicating the application criteria for selecting a location provider. Providers maybe ordered according to accuracy, power usage, ability to report altitude, speed, and bearing, and monetary cost.
code sample :
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
String provider = locationManager.getBestProvider(criteria, true);
Have a look at how to use locationmanager , how to specify Criteria and how getBestProvider method works for reference
In my app I have an AlarmManager set to run an IntentService every so often to make a WebService Call to my server sending your current location
When the alarm is started I also start a Service that has a LocationManager to keep track of the location locally.
When I make the web service call to my server I use
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
String provider = locationManager.getBestProvider(criteria, true);
Location lastKnownLocation = locationManager.getLastKnownLocation(provider);
since I only need the location at this point in time and the next time the web service is called again I just get it again. But it appears even though I have a service running in my background that uses the GPS and gets the right location, calling
locationManager.getLastKnownLocation(provider);
when I make the web service to get the location it gives me a stale location and not the current one. Now I would think that since I already have a locationmanager running in another service that the getLastKnownLocation would get updated to the correct location everytime the onLocationChanged gets called but that is obviously not the case which makes no sense to me.
So my question now is how can I get my correct location in my IntentService since I cannot rely on getLastKnownLocation
I do no need to know the location everytime it changes I just need to know what it is at the time I make the web service call so starting another location manager does not seem like a good idea. The only thing I can think of to solve this is to store the location from my other service in SharedPreferences and just grab whatever is in there but that seems a little hacky and i dont like hacky.
any ideas?
The last known location for android gets updated only when any app requests for a location (app can be yours or any other on the device). You have to implement the location listener and then use locationManger.requestLocationUpdates(provider, minTime, minDistance, locationListener) to ask for the location update. The android system will get the location update on your request and set the lastKnownLocation for all apps to use.
The only reason I can think of the lastKnownLocation not being set is that the android system couldn't get the location. Check that the provider requested for the location update is enabled. Also you can use Passive Provider for piggybacking on the location requests of other apps and actively look for location only if there is no update for certain time out period (This approach should be better that constantly trying to get location updates which are costly).
In my app the GPS takes too much time to get the location.
How can I use GPS from GPS_SATELLITES and GPS _NETWORK_PROVIDERS simultaneously in the same context and get the value of the recent GPS?
Keep track of a Location object that is your current location. Request location updates from both
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
LOCATION_UPDATE_FREQUENCY, LOCATION_UPDATE_MIN_DISTANCE,
gpsListener);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_UPDATE_FREQUENCY,
LOCATION_UPDATE_MIN_DISTANCE, networkListener);
then when you get a response in onLocationChanged of either listener, either simply replace the Location variable you stored or replace it only if it is X seconds more recent, X% more accurate, X meters distant from your last reading, etc.
You can also use LocationManager.getAllProviders(), then call LocationManager.getLastKnownLocation(provider) to retrieve the last location each available provider found the last time it was called. This way, if another app used the GPS a minute ago, you can just go ahead and trust that they user hasn't made it that far away without hunting for satellites all over again.
I have found plenty of examples of creating a location listener where you supply a particular provider, like so:
LocationManager lm =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener ll = new mylocationlistener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
However, I don't need a precise location, but I'll take the best available. Is there a way to create a listener that works for the best available at the given time without creating a listener for each provider?
e.g. Use GPS if it is available, if not, Network, etc. Also, this is a widget, so I don't want to check what is available, then create a listener for that, since the widget will be up for a long duration and may live through enabling/disabling providers.
Thanks for the help
Have you considered using the PASSIVE_PROVIDER? That combined with getLastKnownLocation() might get you most of the way to what you want... You would call getLastKnownLocation() initially to establish a location if one was already known to the device, then the PASSIVE_PROVIDER would listen for updates from any location provider (i.e., location requests triggered from any other application on the device).
There would still be the possible scenario of no other application requesting location, so you'd likely want to trigger at least a single initial location fix using GPS_PROVIDER or NETWORK_PROVIDER.