Here are snippets of my code:
private class NoGpsLock implements Runnable {
public void run() {
if (gps == null) {
Toast toast = Toast.makeText(getApplicationContext(), "Unable to find GPS lock", Toast.LENGTH_LONG);
toast.show();
if (locManager != null) {
locManager.removeUpdates(locListener);
}
}
}
}
Called by
try {
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME, MIN_DIST, locListener);
} catch (Exception ex) {
}
Handler gpsHandler = new Handler();
gpsHandler.postDelayed(new NoGpsLock(), 15000); //15seconds
From what I understand, removeUpdates() is supposed to stop the GPS receiving updates. I tried this on the emulator and on 2 devices; on the emulator, it does stop the app from receiving further location changes. However, on the actual devices, the icon for "Receiving location data from GPS" keeps showing up and drains the battery (which I assume indicates that the app/phone keeps on looking for a location and unable to, since I'm indoors). How do I stop the GPS from trying to find a location?
EDIT: I want my app to stop trying to find location after a period of time, and then maybe restart the GPS again later.
removeUpdates(locationListener) is supposed to stop that blinking GPS icon. If it isn't doing that, the best suggestion I can offer is that maybe there are there are other listener instances still registered with your locationManager? A forgotten for-loop could have attached other listener instances. As a brute-force developer I'd do removeUpdates() multiple times to see if that has any effect.
Related
OLD QUESTION:
I'm trying to get my device's location coordinates and I've followed all the steps that I've found in multiple areas while researching. I've set up a LocationManager and used the requestLocationUpdates function that is tied to a LocationListener. However, the LocationListener does not respond. I've tried debugging as well as walking around outside in order for the onChangedLocation function to execute but nothing happens. In debugging the requestLocationUpdates function for my LocationManager is executed but the LocationListener is never executed.
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
textView = (TextView) findViewById(R.id.textView);
textView2 = (TextView) findViewById(R.id.textView2);
locationListener = new myLocationListener();
textView.setText("Longitude", TextView.BufferType.NORMAL);
textView2.setText("Latitude", TextView.BufferType.NORMAL);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, locationListener);
requestLocationUpdates
Above is the use of the requestLocationUpdates function.
private class myLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location location) {
//Log.e("Latitude: ", "" + location.getLatitude());
//Log.e("Longitude: ", "" + location.getLongitude());
if(location != null)
{
textView.setText(Double.toString(location.getLongitude()), TextView.BufferType.NORMAL);
textView2.setText(Double.toString(location.getLatitude()), TextView.BufferType.NORMAL);
}
else
{
textView.setText("No Location", TextView.BufferType.NORMAL);
textView2.setText("No Location", TextView.BufferType.NORMAL);
}
Toast.makeText(getApplicationContext(),"onLocationChanged Success",Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
}
myLocationListener
This is myLocationListener that implements LocationListener. I've added a little bit of extra code for testing purposes. The toast would never pop up so it appears as though this code is never executed. If anyone could help me out with this I would really appreciate it.
Thank you!
NEW QUESTION:
After continuing on developing in this page while waiting for a response I noticed that it takes about a minute for the location services to actually begin working. So, now my question is: how do I overcome the obstacle of a user having to wait to use the app? I've seen apps that use location based content and it does not take that long. I know that there is the getLastKnownLocation function but what if a user travels 50 miles before opening the app again? Any help on this would be appreciated. Thank you!
Each device which makes location request for gps, has to wait until gps hardware become warm. The wait time changes by device and where you stay. If you are inside a building, this time could take 1 minute or more.
To avoid wait, you can use getLastKnownLocation method, if returns a cached location, check location's date via getTime method. Determine yourself, is it old location by your scenario ?
if it's too old location, you have to make location request and wait.
I'm trying to find a way to turn off the GPS immidietly in case a good enough location was found, while still having a time limit to "give up".
I tried to do this with the following strategy:
start checking for locations, as soon as a location that has an accuracy lower than the maximum tolerated, pass it to the next function for processing and stop looking for updates.
Also, to save battery life, if such location could not be found in 30 seconds, stop looking for location updates without passing a value (basically give up, and hope to better luck next time).
To count the 30 seconds, I'm using a handler. But as soon as I write the line locationManager.removeUpdates(locationListener); in the handler, the locationListener in the parenteses in both lines (the one in the handler and the one in the listener) turns red and reports an error: The local variable locationListener may not have been initialized
Here is my code:
private void checkProximity() {
final LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
//start tracking location
final LocationListener locationListener = new LocationListener() {
...
#Override
public void onLocationChanged(Location location) {
//if new accuracy is better than the best estimate - update the best estimate
if(location.getAccuracy() < MAXIMUM_TOLERATED_ACCURACY) {
//forward location to scanProximity and end the location search
scanProximity(location);
locationManager.removeUpdates(locationListener); //FIRST LINE (see below)
}
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
500, 0, locationListener);
Handler h = new Handler();
int delay = 30 * SECOND;
Runnable removeListener = new Runnable() {
#Override
public void run() {
//if this code is reached - the maximum tolerated accuracy was not met in the period time
//extended to find a location
//TODO stop the location manager and return without forwarding a value
locationManager.removeUpdates(locationListener); //as soon as I write this line, the FIRST LINE and this line turns red.
}
};
h.postDelayed(removeListener, delay);
}
Is there anyway I can do this differently so I won't get an error?
I recommend you use Little Fluffy Location Library to work with GPS locations. Check out the examples codes and see which makes you more easy the solution to your problem , this is a beautiful way.
I want to know if there is a way in Android (GingerBread) to know if at the moment the GPS is doing something or not. Let me be a bit more clear: I basically want to call some method or api that will tell me wheter the GPS is:
1)Fixed (GPS icon in statusbar on)
2)Searching for fix (GPS icon on statusbar blinking)
3)Inactive (No app is using location services at the moment, no icon on statusbar)
Now: I know that you can use a LocationListener to be notified of such changes BUT this is not good for me because I don't want my code to remain running waiting waiting for events, my code runs periodically at scheduled times, does something and then terminates, so I need a way to check the status of the GPS service in that precise moment, rather than wait for notifications of when it changes.
After doing lot of testing on GPS, finally I found the solution. When android app calls location manager and GPS starts searching, one event is triggered and also when gps is locked another event is triggered. Following code shows how to do this.
locationManager = (LocationManager)mContext.getSystemService(LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isGPSEnabled) {
if (locationManager != null) {
// Register GPSStatus listener for events
locationManager.addGpsStatusListener(mGPSStatusListener);
gpslocationListener = new LocationListener() {
public void onLocationChanged(Location loc) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES_GPS, MIN_DISTANCE_CHANGE_FOR_UPDATES_GPS,
gpslocationListener);
}
}
/*
* This is GPSListener function invoked when various events occurs like
* GPS started, GPS stopped, GPS locked
*/
public Listener mGPSStatusListener = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
switch(event) {
case GpsStatus.GPS_EVENT_STARTED:
Toast.makeText(mContext, "GPS_SEARCHING", Toast.LENGTH_SHORT).show();
System.out.println("TAG - GPS searching: ");
break;
case GpsStatus.GPS_EVENT_STOPPED:
System.out.println("TAG - GPS Stopped");
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
/*
* GPS_EVENT_FIRST_FIX Event is called when GPS is locked
*/
Toast.makeText(mContext, "GPS_LOCKED", Toast.LENGTH_SHORT).show();
Location gpslocation = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(gpslocation != null) {
System.out.println("GPS Info:"+gpslocation.getLatitude()+":"+gpslocation.getLongitude());
/*
* Removing the GPS status listener once GPS is locked
*/
locationManager.removeGpsStatusListener(mGPSStatusListener);
}
break;
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
// System.out.println("TAG - GPS_EVENT_SATELLITE_STATUS");
break;
}
}
};
It is better to put GPS code in and as service to get GPS location information.
Each time if you call GPS function, GPSStatus listener is registered. GPS_SEARCHING toast comes only once when GPS is started to search and GPS_LOCKED toast displays when GPS is locked. If we call GPS function again, GPS_EVENT_FIRST_FIX event is triggered if it is locked(displays GPS_LOCKED toast) and if GPS is already started to search it won't display GPS_SEARCHING toast(i.e GPS_STARTED event won't trigger). After GPS_EVENT_FIRST_FIX event is triggered i'm removing the GPSstatus listener updates.
When GPS_EVENT_FIRST_FIX event is triggered, its better to call gpslastknownlocation() function to get fresh latest GPS fix.(Its better to look into Android developers site for more info).
I hope this will help others....
Unfortunately, there's no easy way to get the "current state" of the GPS in Android. Like others have pointed out, your best bet is to register for the onGpsStatusChanged() event and track the state.
If you are feeling adventurous, you can call call $ dumpsys location from an adb shell to get the state of the gps provider. You usually call $ adb shell from your desktop, but you can compile a native android shell app, and call an exec() from inside the shell to get the dumpsys output directly on the phone.
I have created application that gets a relevant lat and long and updates in a database. The problem is that when I under a roof like house or mall... I keep getting the GPS searching ICON on my app.
I am using a button to trigger the Mylocation() and it's listener.
The button has the following:
locationListener = new MyLocationListener();
location.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 5, locationListener);
and under the mylocationlistener method I have
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
try {
Thread.sleep(1000);
Toast.makeText(getBaseContext(),"Location: Lat:" + loc.getLatitude() + " Lng:" + loc.getLongitude(),Toast.LENGTH_SHORT).show();
location.removeUpdates(locationListener);
location = null;
finish();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
I get the value toasted properly without any problem and app is finished an GPS icon goes away but when I am inside the roof and GPS icon in top keeps searching for GPS. The icon doesn't go away.
How do I fix this? Do I need to put a condition if Gps signal is good start the GPS if not just message GPS signal not good. if so how?
Thanks!
As described in this question How to measure GPS signal strength on Android,
So assuming that you really mean signal strength, you can get the GpsStatus via LocationManager.getGpsStatus(), and that gives you a list of satellites via getSatellites(), and each one of those has a signal-to-noise ratio (getSnr())
You could consider using the network location service as well as or instead of GPS. You could also consider adding a timeout.
Details:
I have a service that needs to do the following:
- listen constantly for GPS locations, with 50 meters as parameter (works fine) and send it to a server
- each 60 seconds, if no GPS location was read, start listening for a Network location and send it to the server
This may sound weird, but this is the project requirement. So the user is constantly being tracked using GPS. When he stops, or GPS is not locked, or is inside a building, every 60 seconds start a quick Network location read, and send this location to the server. As the service uses the same thread as the main app, each server update is done in its own thread. And another important thing: each location read should be sent one after another, so for instance if the user is driving, and multiple reads are done, each should be send to the server, after the previous one has been sent. That's why I decided to use ScheduledExecutorService as I can submit threads and they will be execute one after another.
Here is the code:
private ScheduledExecutorService scheduleTaskExecutor;
Handler locationHandler = new Handler();
private Location lastNetworkLocation;
#Override
public void onStartCommand() {
scheduleTaskExecutor = Executors.newSingleThreadScheduledExecutor();
//prepare to execute Network reading every 60 seconds
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
initNetworkReadings();
//usually a network location read is done almost instantly
//however after 5 seconds I check if a location has been read by the Network listener inside the locationRunnable
locationHandler.postDelayed(locationRunnable, 5000);
}
}
}, 60, 60, TimeUnit.SECONDS);
locationRunnable = new Runnable() {
#Override
public void run() {
if (lastNetworkLocation !=null){
//send location to the server if valid
}
lastNetworkLocation = null;
}
}
}
private void initNetworkReadings() {
locationManager.removeUpdates(locationListenerNetwork);
try {
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
if (isGpsEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
}
}
LocationListener locationListenerNetwork = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
lastNetworkLocation = location;
// stop listening for Network locations
locationManager.removeUpdates(locationListenerNetwork);
}
...
}
Each time I read a GPS location I add it to the threads queue as:
scheduleTaskExecutor.submit(new Runnable() {
#Override
public void run() {
updateLocationOnServer(readLocation);
}
});
The problem I have is that the Network location listener never gets onLocationChanged() called,when I use it like in the code above, in the Runnable. BUT if I add on service start, the initNetworkReadings(), I get onLocationChanged() fired right away. So I believe it has something to do with being used in scheduleAtFixedRate.
What do you think it could be the problem ? Anything bad in the way I thought of the workflow ?
What if you try to set up your repitition with a Handler and a Runnable instead of scheduleAtFixedRate()?
Handler h = new Handler();
Runnable run = new Runnable(){
//Do your repeititive work here!
h.postDelayed(run, 60 * 1000);
};
h.post(run);
Same problem,
I have a background service that detect locations.
If network is avaible, it uses networks, otherwise it uses gps.
It works well with many smartphones
( nexus s 4.1, galaxy nexus 4.2, galaxy note) , but with Galaxy s3 jb (4.1) network location never rises any location.
Same code with gps locations, works just fine.