How can I change the LocationManager to get just one location? The app keeps updating the location.
public void onClick(View view)
//this make the app keep update
locationManager.requestLocationUpdates("gps", 0, 0, listener);
The first approach would be to use locationManager.requestSingleUpdate() instead of locationManager.requestLocationUpdates()
OR
the second solution is to unregister the listener immediately after you received the first update, as follows:
#Override
public void onLocationChanged(Location location) {
locationManager.removeUpdates(this);
// do something with the received location
}
Related
I have tried (but in vain) to force request GPS location updates on my Android Widget (Android Oreo).
The widget is set to update every 15-20 minutes and fetch the current location of the phone and display.
However, it only picks up the location of the phone where it was installed and subsequent runs don't return a new location even when the phone moves.
I read through the solution provided here How does it work - requestLocationUpdates() + LocationRequest/Listener and implemented it, but it doesn't seem to help.
LocationManager locationManager = (LocationManager)
context.getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
300000L, 500.0f, new LocationListener() {
#Override
public void onLocationChanged(android.location.Location location) {
if(location != null)
{
LocationPreferences.setLastLocationLatLon(context,location);
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
});
Having said that, it is more reliable when it's in one of the activities (and not in a widget), but given that the widget is supposed to perform background location updating, it doesn't work, the onlocationchanged never gets called (I'm sensing it's silently killed in the background)
Has anyone created/ worked with Android widgets using GPS on Oreo? Any help in the right direction will be appreciated. Thank you very much in advance.
I have an AlarmManager that triggers every 30 minutes to an IntentService, and this intent service is to get the user's location each time. I have 2 ways of getting location: first it checks the getLastKnownLocation(), and if it was within the last 2 minutes it uses that, this part works perfectly.
The second way is if the last location was old or returns null, in which I want to get the new location once. For some reason this never calls onLocationChanged(). This results in my IntentService not returning coordinates much of the time, it only returns them if the getLastKnownLocation() was recent.
Here is my code for how it is set up, why is it that if I want to get a new location, it is never called? Check the comments in the code to see what is called and what is never called.
LocationListener locationListener;
LocationManager locationManager;
private final double MIN_COORD_DIFF = 0.0006;
public CoordinateAlarmReceiver(){
super("CoordinateAlarmReceiver");
}
#Override
protected void onHandleIntent(Intent intent) {
//THIS IS CALLED CORRECTLY
MyLog.i("coordinate alarm received");
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Location lastLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//if last location was in past 2 minutes, use that
if(lastLocation != null && lastLocation.getTime() > Calendar.getInstance().getTimeInMillis() - 2 * 60 * 1000) {
//THIS IS CALLED CORRECTLY
storeLocation(lastLocation);
MyLog.i("Last location was recent, using that");
}
else { //otherwise get new location
//THIS IS CALLED CORRECTLY
MyLog.i("Last location was old, getting new location");
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
//THIS IS NEVER CALLED
MyLog.i("Got new coordinates");
storeLocation(location);
locationManager.removeUpdates(this);
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
}
You should use a Service instead of a IntentService. The IntentService finish when complete the task however, the service is running and can listen the location change events. Try to use a service.
Hope it helps you!!
My app uses google map to show user's location in real time. Therefore I would like it to be updated with every data change on my Parse server.
I've looked all over the net and as I see it I have 3 options:
using syncAdapter - the problem is that everywhere it is written that it does not meant for real time data transfer (I don't really understand why), on other hand it must be more efficient than updating every 5 sec.
using asyncTask - the problem is that it probably consumes a lot of battery and data usage to run it every 5 sec.
using service - same problem as asyncTask.
As i'm very confused, please help me understand what is the appropriate way to implement my real time map.
Thank's all
The best way i know is to use LocationListener to update the location only if it has been changed. You can use the onLocationChanged() method to update the location.
public class LocationHelper {
private LocationManager locationManager;
private Location currentLocation;
public LocationHelper(Context context) {
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
public void setLocation(Location location) {
currentLocation = location;
}
private final LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
setLocation(location);//Only update location if it has changed.
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
};
}
If the location hasn't been changed, you can just remember the last known location.
*Please have a look at the below written source code lines and suggest:-*
In the below mentioned code lines I am trying to request for GPS and Network location in every 60 seconds.
if (gps_enabled)
{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0, locationListenerGps);
}
if (network_enabled)
{
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60000, 0,
locationListenerNetwork);
}
Below mentioned is the code for location change listeners:-
LocationListener locationListenerGps = new LocationListener()
{
public void onLocationChanged(Location location)
{
mCurrentGpsLocation = location;
String userCurrentGpsLocation = findUserAddress(mCurrentGpsLocation, mPreviousGpsLocation);
mPreviousGpsLocation = location;
for(int i = 0, size = mLocationUpdateListeners.size(); i<size; i++)
{
LocationUpdateListener listener = mLocationUpdateListeners.get(i);
listener.recieveGpsNotification(userCurrentGpsLocation);
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
LocationListener locationListenerNetwork = new LocationListener()
{
public void onLocationChanged(Location location)
{
mCurrentNetworkLocation = location;
String userCurrentNetworkLocation =findUserAddress(mCurrentNetworkLocation, mPreviousNetworkLocation);
mPreviousNetworkLocation = location;
for(int i = 0, size = mLocationUpdateListeners.size(); i<size; i++)
{
LocationUpdateListener listener = mLocationUpdateListeners.get(i);
listener.recieveNetworkNotification(userCurrentNetworkLocation);
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
And on receiving location change event for GPS and Network, I simply call my listeners recieveGpsNotification() and recieveNetworkNotification() methods respectively.
Logic of recieveGpsNotification() are as follows :-
public void recieveGpsNotification(String gpsLocation)
{
sendEmail();
}
**Problems :-
1) I expect call to sendMail() should come after every 60 sec but I am receiving notifications very frequently and after 4-5 notifications my application crashes. Please help if you see any error in implementation logic.
2) Will i also receive notifications for GPS even when my activity is in pause state or in stopped state, because i want to receive notification even when my activity is in background or it is stopped?
Additional Query :-
Whenever android framework provides us with GPS location updates, every time notification come through a different thread or is it the thread that request for notifications?
Thanks in Advance.
**
Try adding a min distance to each update. Also consider grouping the updates together for your sendEmail() method
Move your Location Listener logic into a Service that runs in the background. This will keep the updates coming. However, be aware that GPS updates are awful for battery life and users will not be happy to see GPS trying to get a lock all the time.
I believe those updates happen on the thread in which they are declared. So you should move your findUserAddress() method and other complex operations to a different thread.
Also, You should only use one method to get GPS updates. The normal use case is to try GPS Adapter, if not enabled or preset, fall through to use the Network listener. Since you have both you will be getting both updates on different intervals.
My app checks at a specific time whether a user is at a given location. I use the alarm manager to start a service that makes this call:
locationManager.requestLocationUpdates(bestProvider, 0, 0, listener);
And also checks:
locationManager.getLastKnownLocation(bestProvider);
But I'm having problems when running on a real device. For one thing, getLastKnownLocation is most likely the last place the GPS was on, which could be anywhere (i.e., it could be miles from the user's current location). So I'll just wait for requestLocationUpdates callbacks, and if they aren't there within two minutes, remove the listener and give up, right?
Wrong, because if the user's location is already stable (i.e., they've used GPS recently and haven't moved) then my listener will never be called because the location doesn't change. But the GPS will run until my listener is removed, draining the battery...
What is the right way to get the current location without mistaking an old location for the current location? I don't mind waiting a few minutes.
EDIT: It's possible that I'm wrong about the listener not being called, it may just take a little longer than I thought... Hard to say. I'd appreciate a definitive answer still.
The code may be something like that:
public class MyLocation {
Timer timer1;
LocationManager lm;
public boolean getLocation(Context context)
{
lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
timer1=new Timer();
timer1.schedule(new GetLastLocation(), 20000);
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
lm.removeUpdates(this);
//use location as it is the latest value
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
class GetLastLocation extends TimerTask {
#Override
public void run() {
lm.removeUpdates(locationListenerGps);
Location location=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//use location as we have not received the new value from listener
}
}
}
We start the listener and wait for update for some time (20 seconds in my example). If we receive update during this time we use it. If we don't receive an update during this time we use getLastKnownLocation value and stop the listener.
You can see my complete code here What is the simplest and most robust way to get the user's current location on Android?
EDIT (by asker): This is most of the answer, but my final solution uses a Handler instead of a Timer.
If the user's location is already stable, then getLastKnownLocation will return the current location. I'd call getLastKnownLocation first, look at the timestamp (compare Location.getElapsedRealTimeNanos() with SystemClock.elapsedRealTimeNanos()) then register a listener if the fix is too old.