It seems for me it is getting called the first time the activity starts, just after onCreate, it then seems to be called at random intervals, whether I move or not???
Regardless of that is it simply called automatically if I have code like this in the onCreate method?
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
Is that right???
Cheers,
Mike.
Your question is not clear initially.Your code and title are not matching. I am giving answer for your title only.
You have to register Location Listener for your Location Manager, then only onLocationChanged() will be called according the settings you supplied while registering location listener.
See below code how to do that. I used GPS Provider, you can use any provider based on criteria also.
LocationManger lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
});
Coming to your question, onLocationChanged() will be called if the current location update is not matching with last known location.
The updated location will be changed for every minTime (in my case 1000 milli sec) and also if device moved minDistance (in my case 0 meters) distance.
I hope you will understand this.
if you want to catch new locations, you have to register a LocationListener like this:
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
LocationListener listener = new LocationListener() {
...
}
locationManager.requestLocationUpdates(GPS_PROVIDER, intervall, distance, listener);
With intervall and distance you can configure:
If intervall is greater than 0, the LocationManager could potentially rest for intervall milliseconds between location updates
If distance is greater than 0, a location will only be broadcasted if the device moves by distance meters.
When the LocationListener is registered, the LocationManager starts to get your geo location and calls the onLocationChanged(). If the distance is very low, it can happen that the method is called very often in a short period of time. According to the intervall, the LocationManager will rest afterwards.
I think, the LocationManager will only start doing it's work, when a LocationListener is registered.
Hope that helps...
Cheers,
Tobi
public void onLocationChanged(Location location)
the above method gets called automatically once your location has been changed..
Related
I have been trying to find the location obtained by GPS_Provider and Network_Provider for every 5 minutes and at the same time stamp for the two values obtained at any specific time.
I tried using the following location strategy given
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, 300000, 0, locationListener)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,300000, 0, locationListener)
But here the Location Manager will call the onLocationChanged() method of the listener if the time since last location update is greater than the notificationInterval.
This brings me some time stamp difference between values generated by GPS_Provider and Network_Provider after every 5 minutes.Is there any way such that I can find the location that GPS_Provider and Network_Provider generate at a same time stamp.
Example:
Now: GPS_Provider(lat,long) at 09:35:12 , Network_Provider(lat,long) at 09:35:14
I need: GPS_Provider(lat,long) at 09:35:12 , Network_Provider(lat,long) at 09:35:12
In short, no.
The location api doesn't work in a synchronous way, meaning you have no guarantee when exactly you'll get the update. the time frames which you supply state the maximum interval between updates.
Having said that, you could start the updates with lower interval (such as 50ms) and get a bunch of updates, sort them by the second of the timestamp and get the ones which have the same value.
Update
You can use the getLastKnownLocation method to get the last location known by the provider, check the docs here.
I have following code:
LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
and MyLocationListener class:
public class MyLocationListener implements LocationListener{
#Override
public void onLocationChanged(Location loc){
loc.getLatitude();
loc.getLongitude();
tv_GPSlat.setText("Latitude: " + loc.getLatitude());
tv_GPSlon.setText("Longitude: " + loc.getLongitude());
}
#Override
public void onProviderDisabled(String provider){
Toast.makeText( getApplicationContext(),"GPS is not working", Toast.LENGTH_SHORT ).show();
}
#Override
public void onProviderEnabled(String provider){
Toast.makeText( getApplicationContext(),"GPS is working",Toast.LENGTH_SHORT).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras){
}
}
I would like to save current longitude and latitude to my TextViews (tv_GPSlat, tv_GPSlon) but the location values are not constant (they are changing all the time). How can I do this?
GPS isn't exact- even if you don't move it will bounce around a bit. Just put up the first location you get, and ignore future updates unless they move by more than a certain amount. That's the easiest way to do it.
You have to get the location and once you get it (i.e. your handler method is invoked) you have to unregister the handler in order to stop receiving the updates. Simply add this line at the end of your handler method onLocationChanged() in MyLocationListener:
LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
mlocManager.removeUpdates(this);
Add a data member to your location listener, and keep the previous location in it:
public class MyLocationListener implements LocationListener {
public Location mSavedLocation;
#Override
public void onLocationChanged(Location loc) {
// If we don't have saved location, or the distance between
// the saved location and the new location is bigger than
// 5 meters (~15ft) save the new location
if ((mSavedLocation == null) ||
(loc.distanceTo(mSavedLocation) > 5)) {
mSavedLocation = loc;
}
// Update the screen with the current saved location
tv_GPSlat.setText("Latitude: " + mSavedLocation.getLatitude());
tv_GPSlon.setText("Longitude: " + mSavedLocation.getLongitude());
}
// ... no changes to the rest of the class
}
Now the rest of your code can also get the latest saved location using:
mlocListener.mSavedLocation
I wonder why no one mentioned this. May be I a missing something. The call you have made has 0,0. It should have milliseconds, distanceinmeters. This way location change is only called when a particular distance is traveled OR after a time out. I am using both GPS and NETWORK providers to not be dependent on either too (sometimes GPS is not reliable).
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, God.KM20TIME,
God.KM20DISTANCE, (LocationListener) updates);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, God.KM20TIME,
God.KM20DISTANCE, (LocationListener) updates);
my app need use new current GPS parameter(update after each from 3 to 8 second): latitude and longitude. and i am using both: GPS-provider and Network-provider.
i know use to update the GPS parameters
if(gps_enabled)
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
if(network_enabled)
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
The Problem: in fact, the gps update after each environ 40-50 second
How can i get the GPS update after 3-8 seconds ??
thanks you
try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}
//lm is locationManager
In fact. i don't use the condition: network_enabled or Network-provider to get Location. ---> It work and the new code:
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, locationListenerGps);
The reason, i don't use the Network_Provider. Because, when 2 GPS and Network Provider, system will use the NEtwork_provider. But in the logcat, i see that Smartphone does not update"Listenter" loop 3-6s with Network_provider.
En revanche, with GPS_PROVIDER, smartphone update alway 3-6s.
-- First time when open GPS; i need 30-50second to have the first Listener. But it is OK
I've written a little app that will return position, average speed and current speed. When I run it on my phone (HTC Legend) it updates 1-2 times a second. You're more than welcome to use it if you like. you just need to create a main.xml file with 6 textviews and then add this line to your AndroidManifest.xmll file:
package Hartford.gps;
import java.math.BigDecimal;
import android.app.Activity;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
public class GPSMain extends Activity implements LocationListener {
LocationManager locationManager;
LocationListener locationListener;
//text views to display latitude and longitude
TextView latituteField;
TextView longitudeField;
TextView currentSpeedField;
TextView kmphSpeedField;
TextView avgSpeedField;
TextView avgKmphField;
//objects to store positional information
protected double lat;
protected double lon;
//objects to store values for current and average speed
protected double currentSpeed;
protected double kmphSpeed;
protected double avgSpeed;
protected double avgKmph;
protected double totalSpeed;
protected double totalKmph;
//counter that is incremented every time a new position is received, used to calculate average speed
int counter = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
run();
}
#Override
public void onResume() {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, this);
super.onResume();
}
#Override
public void onPause() {
locationManager.removeUpdates(this);
super.onPause();
}
private void run(){
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setSpeedRequired(true);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
//Acquire a reference to the system Location Manager
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
locationListener = new LocationListener() {
public void onLocationChanged(Location newLocation) {
counter++;
//current speed fo the gps device
currentSpeed = round(newLocation.getSpeed(),3,BigDecimal.ROUND_HALF_UP);
kmphSpeed = round((currentSpeed*3.6),3,BigDecimal.ROUND_HALF_UP);
//all speeds added together
totalSpeed = totalSpeed + currentSpeed;
totalKmph = totalKmph + kmphSpeed;
//calculates average speed
avgSpeed = round(totalSpeed/counter,3,BigDecimal.ROUND_HALF_UP);
avgKmph = round(totalKmph/counter,3,BigDecimal.ROUND_HALF_UP);
//gets position
lat = round(((double) (newLocation.getLatitude())),3,BigDecimal.ROUND_HALF_UP);
lon = round(((double) (newLocation.getLongitude())),3,BigDecimal.ROUND_HALF_UP);
latituteField = (TextView) findViewById(R.id.lat);
longitudeField = (TextView) findViewById(R.id.lon);
currentSpeedField = (TextView) findViewById(R.id.speed);
kmphSpeedField = (TextView) findViewById(R.id.kmph);
avgSpeedField = (TextView) findViewById(R.id.avgspeed);
avgKmphField = (TextView) findViewById(R.id.avgkmph);
latituteField.setText("Current Latitude: "+String.valueOf(lat));
longitudeField.setText("Current Longitude: "+String.valueOf(lon));
currentSpeedField.setText("Current Speed (m/s): "+String.valueOf(currentSpeed));
kmphSpeedField.setText("Cuttent Speed (kmph): "+String.valueOf(kmphSpeed));
avgSpeedField.setText("Average Speed (m/s): "+String.valueOf(avgSpeed));
avgKmphField.setText("Average Speed (kmph): "+String.valueOf(avgKmph));
}
//not entirely sure what these do yet
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, 1, locationListener);
}
//Method to round the doubles to a max of 3 decimal places
public static double round(double unrounded, int precision, int roundingMode)
{
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(precision, roundingMode);
return rounded.doubleValue();
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
The minTime parameter of requestLocationUpdates should be 3000 to 8000
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener, Looper looper)
minTime the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value.
minDistance the minimum distance interval for notifications, in meters
Take a look at requestLocationUpdates(...)
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
Since: API Level 1
Registers the current activity to be notified periodically by the named provider. Periodically, the supplied LocationListener will be called with the current Location or with status updates.
It may take a while to receive the most recent location. If an immediate location is required, applications may use the getLastKnownLocation(String) method.
In case the provider is disabled by the user, updates will stop, and the onProviderDisabled(String) method will be called. As soon as the provider is enabled again, the onProviderEnabled(String) method will be called and location updates will start again.
The frequency of notification may be controlled using the minTime and minDistance parameters. If minTime is greater than 0, the LocationManager could potentially rest for minTime milliseconds between location updates to conserve power. If minDistance is greater than 0, a location will only be broadcasted if the device moves by minDistance meters. To obtain notifications as frequently as possible, set both parameters to 0.
Background services should be careful about setting a sufficiently high minTime so that the device doesn't consume too much power by keeping the GPS or wireless radios on all the time. In particular, values under 60000ms are not recommended.
The calling thread must be a Looper thread such as the main thread of the calling Activity.
Parameters
provider the name of the provider with which to register
minTime the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value.
minDistance the minimum distance interval for notifications, in meters
listener a {#link LocationListener} whose onLocationChanged(Location) method will be called for each location update
I've been working on an application that emails the GPS location of a phone to the user- and it is very important that the phone sends the current location, not the location from a while ago.
I tried a couple fixes, such as changing minTime and minDist, as well as removing (or not removing) the listener when done. This application is to be used only at certain times, however, and I want minimum battery use, so leaving it running isn't a good option.
I have had luck with some updating if I set the minTime to a small amount, and never removed the LocationListener, in which case the second message I sent would be updated, but other than that...
This makes me think I need to give it more time to get the GPS location for sure- but how would I force it to do that?
With this in mind, I have been trying this snippet:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
};
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, (long)(.000001), (float)(0),
locationListener);
String s = "";
SimpleDateFormat timingFormat = new SimpleDateFormat("hh:mm");
timingFormat.format(new Date());
s += "The current time according to the clock is: "
+ timingFormat.format(new Date()) + "\n";
Location location = lm
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
lm.removeUpdates(locationListener);
(returns the String s, with the address added)
You should put something in onLocationChanged to do something with the location updates coming in.
Normally you first get a rough approximation, and when the GPS tunes in the accuracy gets better. To handle this efficiently, have onLocationChanged check if the location is accurate enough, and let it kick off whatever you want to do with the accurate location.
A good start would be to just put
Log.v("myapp","Location changed: "+location);
in onLocationChanged() and then watch the output.
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.