I am trying to get a periodic update on location at a fixed interval. Right now, I am testing with a 2 minute interval just to make sure things are working. Then I will push it to a much longer interval.
Here is the relevant code:
public final int LOCATION_TIMER_RATE=120000;
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
Log.d("BLAH", "Recorded home location as: (" + location.getLatitude() + "," + location.getLongitude() + ")");
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, LOCATION_TIMER_RATE, 0, locationListener);
If I request a single update, as follows, I always get a response back within 20 seconds or so. But, after that, I still do not get my periodic updates:
locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, locationListener, null);
If you request a single update, do you need to reschedule your periodic updates?
If you request a single update, then yes, you'd have to reschedule it for future updates. As for the requesting period updates not being consistent, it says so in the documentation. The updates can take longer (or possibly even shorter) than the time period you select.
Related
I don't want to use service which is continuously running in background ! Actually in my project user will send SMS command from any smartphone to his/her misplaced smartphone.My app will detect that particular "SMS command" and in return it will send the current location of misplaced mobile.
can it be done through intent service ? I m damn confused ... Its single time operation how to perform it efficiently ... ?
by using NETWORK_PROVIDER getting geolocation
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
and add this permission in manifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
I am currently writing an application that receives location data every minute (or other specified amount of time) and thes send it to server.
The problem that I have noticed is:
When I use my application connected to power source it works perfectly - sends updates with defined interval.
When I use it on battery it sends updates randomly.
For my application I use timer to specify interval of update. This timer runs in Background service. I request updates in timer and remove updates when I receive location.
Fragment of my code:
private class mainTask extends TimerTask
{
public void run()
{
toastHandler.sendEmptyMessage(0);
}
}
private final Handler toastHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
date = date.getInstance(); //used to set time of update.
if(!GPSupdating)
{
locationManager.requestLocationUpdates("gps", 0, 0, locationListenerGPS);
GPSupdating = true;
}
}
};
My location listener:
LocationListener locationListenerGPS = new LocationListener()
{
public void onLocationChanged(Location updatedLocation)
{
myGPSLocation = updatedLocation;
haveLocationGPS = true;
locationManager.removeUpdates(locationListenerGPS);
GPSupdating = false;
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
Do you have any idea why this is not working correctly?
It's not good solution - enable/disable listener on each minute.
Better to try following things:
1) Set minimal update time (in requestLocationUpdates ) to one minute and send data to server in update listener:
locationManager.requestLocationUpdates("gps", 60*1000, 0, locationListenerGPS);
If you need more accurate update intervals, than:
2) Start separate thread and enable GPS updates on it. Store last location in thread or service variable. Also start timer and on timer tick send location to the server.
Try using Criteria to manage the power. Set power requirement to POWER_LOW. You will loose some accuracy though.
LocationManager locationManager= (LocationManager) getSystemService(context);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_LOW);
provider = locationManager.getBestProvider(criteria, true);
You will not save energy by enabling and disabling GPS once per minute. Either choose a greater intervall (5 minute) or get the location evry second.
Then store the location in a lastValidLocation filed, start your own Timer, and once a minute read out lastValidLocation. and send to server if changed.
I have registered my LocationManager for location updates, every 10 seconds
mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, 50, this);
But the onLocationChanged callback returns a location every 10 secs, which(the location) is more than 2 hours old. And that time-stamp is never changing.
The problem is:
2 hours back I was in a complete different location(home) where I used the device on a wifi. Now currently I am in some other location(office) on a different wifi where my application shows my current location as home. Same thing happened at home yesterday, when it was showing office as my current location. It got to work(started showing correct location) when I closed my app, opened FourSquare app and re-opened my app.
Complete Code:
public class LocationService extends Service implements LocationListener {
public static double curLat = 0.0;
public static double curLng = 0.0;
private LocationManager mgr;
private String best;
private Location location;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
best = LocationManager.NETWORK_PROVIDER;
location = mgr.getLastKnownLocation(best);
if (location != null) {
dumpLocation(location);
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10 * 1000, 50, this);
}
return START_NOT_STICKY;
}
}
private void dumpLocation(Location l) {
SimpleDateFormat s = new SimpleDateFormat("dd/MM/yyyy:hh:mm:ss",
Locale.ENGLISH);
String format = s.format(l.getTime());
//The above time is always 28/03/2013:09:26:41 which is more than 2 hrs old
curLat = l.getLatitude();
curLng = l.getLongitude();
}
#Override
public void onLocationChanged(Location location) {
dumpLocation(location);
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
Being started in an Activity this way:
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, LocationService.class);
pi = PendingIntent.getService(this, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), 10000, pi);
Permissions in manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
I can get the correct location now, by opening some other location based app like Maps, Navigator, Foursquare etc.., But why my app isn't able to get a new/fresh fix from the provider.
Thank You
You are getting old location because of this line
location = mgr.getLastKnownLocation(best);
because if GPS is not enabled then it will show you the old location . So remove this code It will work like a champ
You can also refer to this library
https://github.com/nagendraksrivastava/Android-Location-Tracking-Library
On the basis of your comments I have edited the answer Okay Let me explain line by line
location = mgr.getLastKnownLocation(best); it will give you object of last know location then it will go inside if condition and it will call dumplocation and will get last location data and after that you called
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10 * 1000, 50, this);
but suppose GPS provider is disabled then it will not fetch new location so you will get old location only . So either you can change it like
if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,new NagendraSingleLocationListener(),null);
}
else
{
locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,new NagendraSingleLocationListener(),null);
}
I think because you cancel your pending intent right away, thus the requestLocationUpdate would not start update before you cancel. Why don't you sleep may be for 2 second before cancel.
From my experience android will give you a location when you request the updates even if gps has not enough sattelites to work. So even if gps is on - if you are inside or in a location that is bad (like under a bridge) android will deliver an old fix to you. Can be a very old one indeed.
The only thing I found to be working 100% is to generelly not use the first position but only remember the time. When new positions arrive you can check that the time is newer than the last. If you want to only use very precise positions you may also need to check that location.getAccuracy() is low (the lower the better).
I use gps to get my timestamps for a soap interface as the android clock can be very off sometimes and this was the only way for me to get a valid time from gps.
I have tried to do my research about GPS issues before posting here. When I tested my code It repeats the same output over and over. The method gpsStart() is called on a timer. Fine and Coarse location permissions have been added to the manifest. The method appendLog() stores the output in a file.
public void gpsStart() {
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Toast.makeText(getApplicationContext(), "location changed",
// Toast.LENGTH_SHORT).show();
// Called when a new location is found by the network location
// provider.
appendLog("Lat: " + location.getLatitude() + "\nLng: "
+ location.getLongitude()+"\n");
text3.setText("Lat: " + location.getLatitude() + "\nLng: "
+ location.getLongitude());
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
};
// Register the listener with the Location Manager to receive location
// updates
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, locationListener);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
You must not call gpsStart() method in the timer. I am going to say how Location Listener works
What is Location Listener?
Location Listener is the class which notify you when your current location will be change. For receive the location updates you will have to register LocationListener class using LocationManager class.
When to register Location Listener?
It depends on the requirement of your application. For example if you want location listener for display current location on map then you should register Location Listener in onCreate() or onResume() method of the activity and unregister receiver in onPause() or onStop() method. If you want to receive the location even if your application is not running then you can use a service to receive location.
How to Register/Unregister Location Listener?
To register the LocationListener you first need the instance of the LocationManager class which you can get using the context like
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
After then you will have to set the location provider. There are 2 types of providers which are often used.
GPS provider
Network Provider
Now to register the location receiver with this location provider there is a method requestLocationUpdates of LocationManager. In this method first argument is the provider name second argument is the minimum time for request location update. Third argument is the minimum distance to request for the location change.Last argument is for locationListener.
Here how you can use the method
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, minTime, minDistance, locationListener);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, minTime, minDistance, locationListener);
To unRegister location updates you can use the below method
locationManager.removeUpdates(locationListener)
Note: You are calling a method gpsStart in the timer as you have mentioned in your question so it is adding location listener each time when this method calls.So all the listeners are triggering you the new location so probably you are getting same location multiple times. Instead of it, you should call this method once when your activity starts and unRegister this locationListener when your activity finish.
Hopes you are getting. :D
Enjoy!!!
Better you create a 2 listeners.1 for Gps and other for network.
the following are code samples
public class MyLocationListener extends LocationListener
{
public void onLocationChanged(Location location)
{
// Toast.makeText(getApplicationContext(), "location changed",
// Toast.LENGTH_SHORT).show();
// Called when a new location is found by the network location
// provider.
appendLog("Lat: " + location.getLatitude() + "\nLng: "
+ location.getLongitude()+"\n");
text3.setText("Lat: " + location.getLatitude() + "\nLng: "
+ location.getLongitude());
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
}
MyLocationListener gpsListener=new MyLocationListener();
MyLocationListener networkListener=new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, gpslocationListener); locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, networklocationListener);
Thank you very much for your answers. Dharmendra you are correct, I did need to close the LocationListeners, however the answer to my question was much simpler. I needed to change the minimum time (the time the listener waits to get an answer) to a value above zero. The value I needed to change is shown in bold below (MINTIME).
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MINTIME, 0, gpslocationListener); locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MINTIME, 0, networklocationListener);
I am using the location manager's requestLocationUpdates() method to receive an intent to my broadcast receiver periodically. The system is correctly firing the intent to my receiver, and I have been able to use it correctly. The only problem is that the GPS location provider only stays active for a few seconds after the initial location acquisition, and I need it to stay on a little longer so that the location estimates are more accurate.
My question is how to make the GPS location provider stay active for each periodic request that comes from the LocationManager requestLocationUpdates. Does anyone know how to do this?
Try something like this. I think it is the right approach
private void createGpsListner()
{
gpsListener = new LocationListener(){
public void onLocationChanged(Location location)
{
curLocation = location;
// check if locations has accuracy data
if(curLocation.hasAccuracy())
{
// Accuracy is in rage of 20 meters, stop listening we have a fix
if(curLocation.getAccuracy() < 20)
{
stopGpsListner();
}
}
}
public void onProviderDisabled(String provider){}
public void onProviderEnabled(String provider){}
public void onStatusChanged(String provider, int status, Bundle extras){}
};
}
private void startGpsListener()
{
if(myLocationManager != null)
// hit location update in intervals of 5sec and after 10meters offset
myLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, gpsListener);
}
private void stopGpsListner()
{
if(myLocationManager != null)
myLocationManager.removeUpdates(gpsListener);
}
if you keep your LocationListener active, it should continue to receive updates to onLocationChanged() if the fix accuracy narrows. and indeed location.getAccuracy() will tell you the current accuracy
maybe set minTime and minDistance both to 0 to receive updates with greater frequency? will use more battery, but is more preise.
There is a example about get GPS location with timeout.
http://sikazi.blogspot.com/2010/09/android-gps-timeout.html#more
To get GPS location periodically, get the location from onLocationChanged method of locationListener and in onResume method specify the timing in milliseconds for getting periodic updates
onResume
location_manager.requestLocationUpdates(provider, 1000, 1, MainActivity.this);