I'm trying to get the user's location within Android, the code below works however it always returns the same location no matter what I do. I've tested out in the middle of an empty parking lot to ensure the GPS is locked on, and it is. Google maps also shows my location correctly. Is there something wrong with the code below?
public class LocationTestActivity extends Activity implements LocationListener
{
private Location myLoc;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
output = (TextView) findViewById(R.id.output);
myLong = (TextView) findViewById(R.id.longi);
myLat = (TextView) findViewById(R.id.lat);
myRefreshed = (TextView) findViewById(R.id.counter);
mgr = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
#Override
public void onLocationChanged(Location location)
{
timesChanged++;
myRefreshed.setText("Refreshed: " + timesChanged);
myLong.setText("Longitude: " + location.getLongitude());
myLat.setText("Latitude: " + location.getLatitude());
}
}
I'd like to add that I can pass in a location using the emulator with no problem. I also removed the other needed methods required by LocationListener for clarity. Thanks for the help!
First make sure that onLocationChanged() is actually getting called. If your GPS has locked before then there is a chance that onLocationChanged won't get fired at all because the phone thinks that you haven't really moved. Therefore it is not a good practice to rely only on requestLocationUpdates() to get your current location.
In general here is what you should do to get your position:
You should use getLastKnownLocation() first to try locating your current location based on last known position.
Check if the location retrieved from step #1 is within reasonable time (not too old) by calling getTime() in the location and comparing with the current time
If this last known position is considered old (I normally use 5-10 minutes depending on the context of the app) then you start requestLocationUpdates() with specific distance (the app should make assumption that the user has moved within the specified limit of last known position)
Implement the onLocationChanged() as desired
Another note, I notice you are only using GPS, there is a lot of situation where GPS cannot lock and therefore never call onLocationChange(), your code should take account of that and checking Network based triangulation in the case onLocationChange() is not called within specified time
Try getting last location fix
Location loc = mgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
and give some time/distance between each location service request
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
And I hope you have enough patience to wait until your device retrieves the location and onLocationChanged() is triggered ;) Joking.
please check your manifest file whether have you added those permission or not.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
One more thing.Where did you call "removeUpdates()"?
Related
My app is working in Ice Cream Sandwich perfectly well, but now I tried it on KitKat and faced some problems.
The app is kind of server I'm running in my old phone and it provides location when requested. In ICS when the location is requested the GPS icon starts blinking and soon the app receives location update and sends it forward. But now with KitKat the GPS icon does not start blinking when location is requested. The app gives 60s time for finding the GPS location, but usually the GPS isn't even activated during this time. Still now and then the GPS suddenly activates itself (during the 60s) and the location is provided to my app.
Why the GPS doesn't get activated even my app requests location? As said, my app works with ICS without problems. And I do have required permissions set in my manifest.
public variables:
public static LocationManager mlocManager = null;
public static LocationListener mlocListener_fast = null;
onCreate:
mlocListener_fast = new MyLocationListener();
mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
Handling user requested command (location request)
mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener_fast);
What should I do differently to get the GPS location instantly without waiting for sudden location updates/GPS activation, probably triggered by Android or some other app?? Unfortunately I don't have any other Android device I could try this.
EDIT:
It seems that if the app does not request location at startup, then the location request works every time when requested time after time. But if the location was requested (and received) on startup, then the location request does not work anymore. What can cause that? I use exactly the same line (the same location mgr and the same location listener) for location request on startup and later if requested.
Even if the location listener used in startup is different than the one used later, the location request does not work anymore. Tried even initialize the location mngr again just before requesting the location again and it did not help. What's with this??
EDIT2:
It just seems that with KitKat it's not possible to request multiple location requests. I used to have several location listeners for different purposes. For example one for updating location once per hour and another for getting location instantly (user requested update). Now it seems that if I have the 1/60min location listener running as normal, then KitKat location manager fails to handle the instant location requests. Have anyone faced this issue? Would be good to know which Android versions have this issue.
Workaround for this issue is to use only one LocationManager and one LocationListener. If your app has needs for different kind of simultaneous location requests (with different parameters), then you need to implement a "location request handler" which decides which parameters should be used for the location request i.e. which parameters have the tightest requirements for location.
Here is a simple example code that explains the idea of "location request handler":
class LR {
long lock_min_time; // defined in set_lock_lr before using
float lock_min_dist;
boolean lock_active = false;
long idle_min_time = 3600000; // 1 per hour
float idle_min_dist = 200;
boolean idle_active = true;
long fast_min_time = 0;
float fast_min_dist = 0;
boolean fast_active = false;
//constructor
public LR()
{}
public void set_lock_lr(long min_time, float min_dist, boolean active)
{
lock_active = active;
lock_min_dist = min_dist;
lock_min_time = min_time;
System.out.println("LR lock set: "+min_time+", "+min_dist+", "+active);
update_location_request();
}
public void set_idle_lr(boolean active)
{
idle_active = active;
System.out.println("LR idle set: "+active);
update_location_request();
}
public void set_fast_lr(boolean active)
{
fast_active = active;
System.out.println("LR fast set: "+active);
update_location_request();
}
private void update_location_request()
{
// Remove current location request
mlocManager_basic.removeUpdates(mlocListener_basic);
if(fast_active)
{
mlocManager_basic.requestLocationUpdates(LocationManager.GPS_PROVIDER, fast_min_time, fast_min_dist, mlocListener_basic);
System.out.println("LR: fast_active");
}
else if(lock_active)
{
mlocManager_basic.requestLocationUpdates(LocationManager.GPS_PROVIDER, lock_min_time, lock_min_dist, mlocListener_basic);
System.out.println("LR: lock_active");
}
else if(idle_active) // only idle updates
{
mlocManager_basic.requestLocationUpdates(LocationManager.GPS_PROVIDER, idle_min_time, idle_min_dist, mlocListener_basic);
System.out.println("LR: idle_active");
}
}
}
I have successfully implemented the android location example http://developer.android.com/training/location/retrieve-current.html
I can request location updates via button click and the onLocationChanged method will be triggered to update a map view with the current location.
But consider following problem. When the phones location does not change, onLocationChange will not be triggered anymore. When the user touches the map view and swipes to another location manually, another location request will not trigger onLocationChanged and the map view will not get the current location because the phones position has not changed.
My question is, how can I receive a location in onLocationChanged at 0 location difference? I am using LocationClient and LocationRequest classes and not LocationManager, so this wont work:
manager.requestLocationUpdates(best, 10000, 1, locationListener);
Any ideas?
use getLastLocation() mehod of locationClient it will give you last known location, however it may be null sometime, I observe in some devices it is returning null when I restart the device and call that function before starting gps or location client method.
in that case you can invoke getLastKnownLocation but you have to detect that state, simply try to wrap your class that provide you location and once time it is update with R
requestLocationUpdateslistening on updates and once when it is not triggered it invoke getLastKnownLocation
so simply you can wrap it with some class that contains lastLocation or best location field
public class MyLocationProvider implements LocalisationListener{
private Location bestLocation = null;
private LocationManager locationManager;
//constructor and all that stuff...
public Location getBestLocation(){
if(bestLocation == null)
return locationManager.getLastKnownLocation();
else
return bestLocation;
}
//locationListener methods... that should save their result in `bestLocation` field.
}
This is simple draft of my idea.... I didn't compile it ;)
http://developer.android.com/reference/android/location/LocationManager.html#getLastKnownLocation(java.lang.String)
I am developing a proximity alert related project. For that whenever I opened my app, I need to get exact readings of where I am. Even though I am following the right coding practices prescribed by android documentation, I am not getting the expected result.
Why there is no alternative command in entire android Geolocation coding for getLastKnownLocation which will give us where we are earlier not now.
I have did one javascript coding in the same lines. There My code is working properly. The Descriptive address and coordinates where my device is working nice there. Those commands getCurrentPosition and watchPosition are givinga beautiful response via their event handler callbacks. Why there is no getCurrentLocation in android geolocation parlance?
Even though I have followed relevant coding practices, MyLocationListener myLocationUpdate which implements LocationListener is not updating my new location when I am moving from one place to another place. I gave MINIMUM_DISTANCE_CHANGE_FOR_UPDATES as 1(in meters) and MINIMUM_TIME_BETWEEN_UPDATES as 1000 (in milliseconds).
I am giving important code snippets below to understand the problem
in onCreate handler of the activity
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!enabled) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
myLocationUpdate = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,MINIMUM_TIME_BETWEEN_UPDATES,MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, myLocationUpdate);
retrieveLocationButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"Finding Location",Toast.LENGTH_LONG).show();
showCurrentLocation();
}
});
latituteField = (TextView) findViewById(R.id.display_Location);
showCurrentLocation();
in showCurrentLocation function
I am using locationManager.getLastKnownLocation(provider) to retrieving that location.
By using GeoCoder Object and the command geocoder.getFromLocation(latitude, longitude, 1) to get First Address match for the coordinates.
// internal class to handle location cahnge event
private class MyLocationListener implements LocationListener contains all the Overridden functions including public void onLocationChanged(Location location)
But Practically I am getting nothing out of all the application. I have already recorded Time via location.getTime(). It is showing a fixed earlier time, but not the interval i specified.
the problem with getting GPS location is that it isnt available immediately. From my understanding of GPS location provider is that when you request location update, the gpr provider will try to connect to the gps satellites which runs in a separate thread (not entirely sure about it). In the meantime your program is executed normally and there maybe a chance that you wont get any location.
What you can do is use Fused Location Provide which was introduced in this year's IO Event. You can find the tutorial here
DDMS is not able to send location to the emulator. I have tried sending just the location from DDMS but still the emulator is not able to receive location. Nothing appears on the DDMS log when I click the Send button.
I tried sending geo fix from telnet which returns OK but doesn't actually update the location, or if it does I can't read it via my application.
The application works properly in the device, is able to capture test location details but not able to capture location data sent to the emulator either via DDMS or telnet.
I am testing on Android 2.2 emulator. Can anyone let me know what is wrong?
My app (below) is written in C# using Mono for Android and may need fixing (I'm a newbie to all things Android so I could have missed something). OnLocationChanged(Location location) just doesn't seem to fire at all, as if the listener isn't properly defined. Any help appreciated.
Note: The first time I run this Activity the LocationManager.GetLastKnownLocation is null but the test provider stuff isn't accessed. When I run it again GetLastKnowLocation is still null but the test provider stuff is accessed and set. Weird.
[Activity(Label = "Location Demo")]
public class LocationActivity : Activity, ILocationListener
{
private TextView _locationText;
private LocationManager _locationManager;
private StringBuilder _builder;
private Geocoder _geocoder;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.LocationActivity);
_geocoder = new Geocoder(this);
_locationText = FindViewById<TextView>(Resource.Id.TextView1);
_locationManager = (LocationManager)GetSystemService(LocationService);
if (_locationManager.GetLastKnownLocation("gps") == null)
{
_locationManager.AddTestProvider("gps", false, false, false, false, false, false, false, 0, 5);
_locationManager.SetTestProviderEnabled("gps", true);
Location loc = new Location("gps");
loc.Latitude = 50;
loc.Longitude = 50;
_locationManager.SetTestProviderLocation("gps", loc);
}
Location lastKnownLocation = _locationManager.GetLastKnownLocation("gps");
if (lastKnownLocation != null)
{
_locationText.Text += string.Format("Last known location, lat: {0}, long: {1}", lastKnownLocation.Latitude, lastKnownLocation.Longitude);
}
else
{
_locationText.Text += string.Format("Last location unknown");
}
_locationManager.RequestLocationUpdates("gps", 5000, 2, this);
}
public void OnLocationChanged(Location location)
{
_locationText.Text += string.Format("Location updated, lat: {0}, long: {1}", location.Latitude, location.Longitude);
}
public void OnProviderDisabled(string provider){}
public void OnProviderEnabled(string provider){}
public void OnStatusChanged(string provider, Android.Locations.Availability availability, Bundle extras){}
}
Kudos to https://stackoverflow.com/users/170333/greg-shackles for getting me this far.
I think the problem may be with how you're calling RequestLocationUpdates(). That third parameter is the minimum distance the device needs to move before you get updates, so you're telling the system to only send updates after the device has moved 2 meters. If it works on a real device, it's probably because you moved more than 6 feet. :)
Try starting with RequestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this). That will start a stream of updates on a real device, but only one when you press 'Send' in DDMS. Once that works, I would work back from there on how often you get updates.
Also, GetLastKnownLocation() is always null when you start the emulator. It's better for devices since it can send you the network location as a starting estimate, or the GPS location if another program was using it recently.
EDIT
It could also be a permissions issue. Normally you need to alter AndroidManifest.xml to get GPS access. The line is
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
See the docs here.
Call
_locationManager.RequestLocationUpdates("gps", 5000, 2, this);
function before doing any location operations, like below:
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.LocationActivity);
_geocoder = new Geocoder(this);
_locationText = FindViewById<TextView>(Resource.Id.TextView1);
_locationManager = (LocationManager)GetSystemService(LocationService);
_locationManager.RequestLocationUpdates("gps", 5000, 2, this); //this will cause updated location to be retrieved from telnet
Note: Its normal that program works after the first run, so that after the first run your application could get the initial updated location from telnet and that will be enough to not throws an exception
Finally resolved this. When the emulator is launched by VS2010 (i.e. F5, start debugging) it does not behave as expected. Launch the emulator externally using AVD.exe, start a virtual device and deploy the app. to it (using F5, start debugging) and everything works fine.
Why starting the emulator from within or outside VS2010 should make any difference is a mystery I am able to live with. Thanks to everyone for their helpful suggestions.
Does your emulated android image have GPS hardware? The description in the emulator should have "hw.gps=yes".
I had the same symptoms before recreating a new image with the right (emulated) hardware. I found a simple web page that displays the current location was handy when debugging the emulation environment.
So I'm trying to sample the gps coordinates just once in an application. I don't want to create a LocationListener object to constantly get gps updates. I want to wait until receiving the coordinates, and then proceed on to another task.
Here is a code snippet
LocationManager lm = (LocationManager)act.getSystemService(Context.LOCATION_SERVICE);
Criteria crit = new Criteria();
crit.setAccuracy(Criteria.ACCURACY_FINE);
String provider = lm.getBestProvider(crit, true);
Location loc = lm.getLastKnownLocation(provider);
The loc variable is always null in the emulator. I tried using the command "geo fix latitude longitude" to set it, and also I tried using the DDMS way of setting it. Neither method had any effect on the code. Also the snippet isn't causing any exceptions.
Thanks for your help.
The call to request update for a location is not blocking, hence it wont wait there. Also the provider in emulator may not have been started.
A possible check could be to see if the settings in it disable gps provider ? then send geo fix.
However, I would use Location Listener, it would be ideal in your case since you need a geo fix to proceed further.Location Listener is Used for receiving notifications from the LocationManager when the location has changed. You can unregister the listener after first geofix.
Note: It can take some time on device to get current location, and even on device this can return null.
Try using the MyLocationOverlay , create a runnable that does what you need to do with that GPS location, and pass it to
boolean runOnFirstFix(java.lang.Runnable runnable)
Queues a runnable to be executed as soon as we have a location fix.
and then disable the location updates for the MyLocationOverlay.
Edit: The reason the location is null is because at the time that code is run, no geofix has been received.