hi guys I have created a background service which gets the person location and if the distance between the device to the destination is smaller i request location updates more often and I am using the removeUpdates(LocationListener) method... the problem is that i noticed that the listener keeps getting updates and the more the loop is going it keeps get more and more updates. does anyone have any idea why this method doesn't work?
Here is my method for using the new location.
void makeUseOfNewLocation(Location location){
manager.removeUpdates(listener);
mLocation = location;
currentLat = location.getLatitude();
currentLong = location.getLongitude();
Location.distanceBetween(currentLat, currentLong, gateLat, gateLong, results);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
currentDistanceFromDestination = results[0];
Log.d("Current Location", "Lat:"+currentLat+" Long:"+currentLong);
Log.d("Destination Distance", currentDistanceFromDestination+"");
if(currentDistanceFromDestination<3000){
if(currentDistanceFromDestination<50){
Log.d("50m closer", "Calling");
startActivity(callIntent);
stopSelf();
}
if(currentDistanceFromDestination<800){
Log.d("800m closer", "Started listening every 10 seconds.");
Toast.makeText(getApplicationContext(),currentDistanceFromDestination+"", Toast.LENGTH_LONG).show();
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10 ,90 , listener);
}else{
Log.d("3000m closer", "Started listening every 25 seconds");
Toast.makeText(getApplicationContext(),currentDistanceFromDestination+"", Toast.LENGTH_LONG).show();
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 25 * 1000, 300, listener);
}
}
}
Do you initiate the value of your listener between calls?
it might not be the same object so it cannot remove updates to it.
In that case the old listener will still be getting updates with you unable to remove them.
Related
My app is used, amongst other features, for tracking drivers doing delivery work, so we need to track the driver's location constantly. For that, we use a Service that runs in the background and saves the coordinates internally before we send them to a server.
The problem is, as is expected, the more precise we need to get, the more the battery drain increases. To the point where Google Play Console Vitals is showing a way above the average number for wake ups like this:
walarm:com.google.android.location.ALARM_WAKEUP_LOCATOR*
I want to know if I'm doing something wrong or if the only way I can improve the code is by doing minor tweaks.
public class LocationService extends Service implements LocationListener {
private Integer gpsFreqInMillis = 1000 * 10; //10 seconds
private Integer gpsFreqInDistance = 10; //10 meters
...
public void startUpdatingLocation() {
...
final LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, gpsFreqInMillis, gpsFreqInDistance, this);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
try {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, gpsFreqInMillis, gpsFreqInDistance, this);
} catch (java.lang.SecurityException ex) {
Log.i(TAG, "fail to request location update, ignore", ex);
} catch (IllegalArgumentException ex) {
Log.d(TAG, "gps provider does not exist " + ex.getMessage());
}
}
...
#Override
public void onLocationChanged(final Location newLocation) {
//saves location in internal database
}
}
Is there a way I can track a precise location without killing my user's battery? I know I can change the min distance and min time values, but 10m/10s is the most precise option we offer.
Only way around to fix this is to optimize the request callbacks by updating these values in your code to
private Integer gpsFreqInMillis = 1000 * 40; //10 seconds
private Integer gpsFreqInDistance = 20; //10 meters
I am new to android programming. So please forgive me if it is a stupid question.
In my app,I am trying to develop a feature that if the location services would be turned off in a phone, then the app would prompt the user to turn it on by taking them to the location settings page on click of a button. The problem is that after turning on the location settings the phone is taking some time to give the location coordinates due to which the fragment that is suppose to show the coordinates is remaining empty for the same amount of time and is creating a confusion.
What I want to know is, if there is any way that I can schedule the execution of the function which is fetching the location coordinates after being sure that there is some coordinates to fetch.
I am using "getLastKnowLocation()". The code for fetching the location is below:-
public String getLocation()
{
// Get the location manager
LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
String bestProvider = locationManager.getBestProvider(criteria, false);
android.location.Location location = locationManager.getLastKnownLocation(bestProvider);
Double lat,lon;
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
try {
lat = location.getLatitude ();
lon = location.getLongitude ();
}
catch (NullPointerException e){
}
}
Create a boolean variable locationLoaded. In your following lines of code:
try {
lat = location.getLatitude ();
lon = location.getLongitude ();
//set the value of variable to true once you get location
locationLoaded=true;
}
catch (NullPointerException e){
}
Then create a new recursive method, which will keep checking for location, until it is not loaded, like this:
private void keepCheckingLocation(){
if(locationLoaded){
//location is loaded
return;
}
else{
//location is not loaded yet
try {
//wait for two seconds
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//call the method again to check the location
keepCheckingLocation();
}
}
Once you have called this method, it won't let the next line of code execute until the locationLoaded is not true and locationLoaded will only be true, once the location is loaded. So you can use this method whenever you want to wait for the location to get loaded.
Note: Set locationLoaded=false; if you have to check for locations again. It will make code more efficient.
Below is the code I used for getting longitude and latitude within a timertask.
public void onClick(View v) {
isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent) {
try {
gpt = new GPSTracker(MainActivity.this);
System.out.println("Internet is present");
setContentView(R.layout.tracklayout);
TimerTask myTask = new TimerTask() {
#Override
public void run() {
try {
Log.d("flow", "" + "task()");
gpt = new GPSTracker(MainActivity.this);
lc = gpt.getLocation();
if (gpt.canGetLocation()) {
double latitude = gpt.getLatitude();
double longitude = gpt.getLongitude();
Log.d("latitude", "" + latitude);
Log.d("longitude", "" + longitude);
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),"Reached.. ",Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
};
Timer myTimer = new Timer();
myTimer.schedule(myTask, 3000, 30000);
} catch (Exception e) {
e.printStackTrace();
}
} else {
alert.showAlertDialog(MainActivity.this,"Mobile Data is Off","Please Turn On mobile data to proceed", false);
}
}
});
Latitude and longitude are always getting zero even I manually entered co-ordinates through DDMS. There no problem with the code of GPSTracker. Outside timertask it worked fine. What is the problem with this code. Anyone please help
As you are using GPSTracker ,If GPS is not working than you can not have lat and long values for sure, you can't get an accurate location. It may take few minutes or seconds because it depends on lot of constraints like yours position inside building, weather , you device hardware quality etc as you are using sattelite to have locations, So we can say thatit depends on the device and the environment settings ( weather, Location under the sky/inside or outside building,device hardware quality etc as an example).
Why you are not using NETWORK_PROVIDER ?? if you can...
If you want to get a coarse location faster with program than you can get the location using NETWORK_PROVIDER, which isn't that accurate but can get you the location very faster.
Visit for examples
http://www.vogella.com/tutorials/AndroidLocationAPI/article.html
http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/
http://developer.android.com/guide/topics/location/strategies.html
Don't use timertask. Implement LocationListener with that activity. Write the codes in the timertask to OnLocation changed. Not needed to run in paricular time interval because we get the same data if we are in same location.
I've asked a question about Commonware's location poller before and got it to work before. Its still working but there is a problem.
Yesterday, (after a bit of experimenting and code studying lol) I realized that in order to get location using both options (prefer GPS, but if not available use Network) I had to pass the extra as 'BOTH'.
After doing that however, the LocationPollerService doesn't FORCE the GPS to locate me. Let me describe the issue below.
Suppose I have my GPS on, and another app actively using the GPS and maintaining a lock. Now, if I use the LocationPollerService, it will return me the value from GPS. However, when my GPS in on, but isn't locked, LocationPollerService doesn't attempt a lock but merely moves on to Network-based Location which isn't what I need when I have GPS enabled.
I would've added code here but I believe this is question specific to cwac-locpoll and the code is already online.
Here's the link:
Commonware's Location Poller
My question? How do I force the service to attempt a location fix when GPS is on?
Update
Here's where I think it looks for GPS location but doesn't actually attempt one. If you could help, that would be great.
#Override protected void onPreExecute()
{
// Added in enabled check to even check if there is a provider
// enabled.
if (provider.equalsIgnoreCase("BOTH"))
{
if (!locMgr.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
{
Log.i(TAG, "Both providers are disabled");
// There is no provider so fail with the LKL if possible
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Location Provider disabled!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, true);
Location lastLoc = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastLoc == null)
lastLoc = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, lastLoc);
sendBroadcast(toBroadcast);
quit();
return;
}
}
else if (!locMgr.isProviderEnabled(provider))
{
Log.i(TAG, provider + " is disabled");
// There is no provider so fail with the LKL if possible
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Location Provider disabled!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, true);
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, locMgr.getLastKnownLocation(provider));
sendBroadcast(toBroadcast);
quit();
return;
}
onTimeout = new Runnable()
{
public void run()
{
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Timeout!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, false);
Location lastLoc = null;
if (provider.equalsIgnoreCase("BOTH"))
{
Log.i(TAG, "Both provider timed out");
lastLoc = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastLoc == null)
lastLoc = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
else
{
Log.i(TAG, provider + " timed out");
lastLoc = locMgr.getLastKnownLocation(provider);
}
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, lastLoc);
sendBroadcast(toBroadcast);
quit();
}
};
handler.postDelayed(onTimeout, TIMEOUT);
try
{
Log.e(TAG, "Provider: " + provider);
if (provider.equalsIgnoreCase("BOTH"))
{
Log.i(TAG, "Adding both providers");
locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
locMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
}
else
{
locMgr.requestLocationUpdates(provider, 0, 0, listener);
}
}
catch (IllegalArgumentException e)
{
// see http://code.google.com/p/android/issues/detail?id=21237
Log.w(TAG, "Exception requesting updates -- may be emulator issue", e);
quit();
}
}
I am trying to get current location of my android phone and display the longitude and latitude in a toast. Here is a function I wrote. While debugging the code I see that the control never goes inside onLocationChanged function.
From the following android documentation it looks like, when I call "locationMgr.requestLocationUpdates", it should call the callback function onLocationChanged. But that does not seem to happen in my code.
http://developer.android.com/training/basics/location/currentlocation.html
I checked my phone has GPS turned on. I can not figure out what is wrong in the following code. Please help.
public void getCurrentLocation(){
LocationManager locationMgr;
locationMgr = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener listener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// A new location update is received. Do something useful with it
String latitude = "latitude: " + location.getLatitude();
String longitude = "longitude: " + location.getLongitude();
String toastString = "location is" + latitude + "," +longitude;
Toast.makeText( getApplicationContext(),toastString,Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderDisabled(String provider) {
// No code here
}
#Override
public void onProviderEnabled(String provider) {
// No code here
}
#Override
public void onStatusChanged(String provider, int status,Bundle extras)
{
// No code here
}
};
locationMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,0, 0, listener);
}
I also have following two lines in my Manifest file.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Thank you for your help.
I am using Eclipse and my phone(OS: Thuderbolt) has API level 15, target 4.0.4.
There are several reasons that you are not getting location.
1.) If you are trying to get location on emulator. Then you have to manually push the coordinates using DDMS.
2.) If You are checking it on device and still you are not getting location. Then as you said that you are expecting it from GPS. Then you should have Clear sky view to get that. As GPS receiver dont work under roofs or under some hinderances. They must have sky view.
3.) You can get location from using wi-fi or cell-Tower. Also you can opt for Last known location if location accuracy is not as much important.
What i think is that may be second point will resolve your problem.
The problem was google-play-services library.
I had to download the library code and compile it in eclipse. Then I added the path to the library in my project. This solved the problem.
Earlier I had included the google-play-services .jar file in my project, but it was not working. Not sure why.
Here is example i wrote that uses LocationManager to get the location data every two minutes. Its not perfect but should be sufficient to solve your issue: It can be found here
Focus on:
#Override
public void onLocationChanged(final Location location) {
this.location=location;
final Handler handler = new Handler();
Timer ourtimer = new Timer();
TimerTask timerTask = new TimerTask() {
int cnt=1;
public void run() {
handler.post(new Runnable() {
public void run() {
Double latitude = location.getLatitude();
Double longitude = location.getLongitude();
Double altitude = location.getAltitude();
Float accuracy = location.getAccuracy();
textView.setText("Latitude: " + latitude + "\n" + "Longitude: " + longitude+ "\n" + "Altitude: " + altitude + "\n" + "Accuracy: " + accuracy + "meters"+"\n" + "Location Counter: " + cnt);
try {
jsonData = new JSONObject();
jsonData.put("Latitude", latitude);
jsonData.put("Longitude", longitude);
jsonData.put("Altitude", altitude);
jsonData.put("Accuracy", accuracy);
System.out.println(jsonData.toString()); //not required, for testing only
if(url!=null) {
new HttpPostHandler().execute();
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cnt++;
}
});
}};
ourtimer.schedule(timerTask, 0, 120000);