LocationManager requestLocationUpdates minTime OR minDistance - java

I'm using Android's LocationManager and its method requestLocationUpdates like this:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 10, this);
As I found out both the conditions of minTime and minDistance have to be met for location update, but I need to get update every 3 seconds or 10 meters.
I tried to put 2 requests like this:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 10, this);
but it doesn't work, I only get update every 10 meters with this code, not every 3 seconds.
I'm working with API19 if that matters.

The Documentation on requestLocationUpdate() says :
requestLocationUpdates(String provider, long minTime, float
minDistance, LocationListener listener)
Register for location updates using the named provider, and a pending intent.
So you should be calling it like locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 10, this);
But If you set minTime to 0, it will be called once when it first receives a location update, then it won't be called until you change your position in minDistance meters.
Documentation Link for Reference
EDIT
As per the Discussion with #Matej I need to get update every 10 meters even if it happened in less than 3 seconds, and update every 3 seconds even if the location didn't change by more than 10 meters
If you want to regularly requestLocationUpdates, you should use Timer and TimerTask and have requestLocationUpdates run once every 3 seconds
schedule(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-delay execution,
beginning after the specified delay.

I read this discussion for a similar problem.
I had to update location every second, but setting:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
I didn't achieve my goal.
In the official documentation I read that also if you fix a timerate for updates, it could be not keeped so rigid as setted. (I can't find anymore the developper page which talk about).
To have a fixed and sure timerate for updates I found this post.
My problem was that Location updates went to update (by observers) the activity and I got error using Timer (as suggested).
the error was:
Only the original thread that created a view hierarchy can touch its views.
For anyone has similar problem I suggest to use Handler:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
notifyLocationObservers();
}
}, 1000);

Related

AlarmManager inconsistent behavior (alarm firing multiple times, or not at all)

I have a button that sets an Alarm using the AlarmManager.setRepeating and another button that removes it, every time an alarm is set the requestCode in the PendingIntent is iterated as to not confuse it with one that has already been set and canceled (the app will have multiple alarms set at the same time in the future). when i set the alarm (setRepeating) sometimes it works as intended sometimes it will fire off twice really quickly than at the time it was intended to go off 2-3 minutes later (i'm setting the alarm 3-5 minutes in the future for my test).
Also note: I have the device plugged in and the screen is set to stay a wake, during testing the app is usually always in foreground, sometimes i put it to background or rotate the screen (usually by mistake).
I have tried setExact() but i don't mind if its off by 0-5 minutes but i do need it to go off and not repeat.
i have played around with the initial time setting it to have started the day before at the hour and minute i want it to go off, same thing with ten days back and a hundred (just to see what would happen) similar results.
I am using Joda DateTime to get the milliseconds of the alarm time for the setRepeating method, and using AlarmManager.INTERVAL_DAY to set the intervals for the next alarm (my alarms need to go off every 24 hours)
requestCode is a constant int that i increment and track during testing.
context i get from getBaseContext() in the activity
My code to set the alarm:
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(ALARMS_INDEX_KEY,requestCode);
PendingIntent sender = PendingIntent.getBroadcast(context, requestCode, intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);//After after 5 seconds
addAlarmIndex(context, requestCode);
//test: DateTime.now().minusDays(10).withTimeAtStartOfDay()
DateTime set_for = DateTime.now().withTimeAtStartOfDay().withHourOfDay(14).
withMinuteOfHour(34).withSecondOfMinute(0).
withMillisOfSecond(0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, set_for.getMillis(), AlarmManager.INTERVAL_DAY , sender);
My code to cancel the alarm:
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, requestCode, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
My code in AlarmManagerBroadcastReceiver extends BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "test_alarm:");
wl.acquire();
int alarm_index = -1;
if(intent.hasExtra(ALARMS_INDEX_KEY)){
alarm_index = intent.getIntExtra(ALARMS_INDEX_KEY,-1);
}
Log.i("medic_debug_timertest","Alarm !!!, fired #: "+DateTime.now().toString("YYYY/MM/dd # HH:mm:ss") + " alarm_index: " + requestCode);
wl.release();
}
What i'm expecting is the alarm gets set before the time it is meant to go off, than the alarm going off at the time it was set to go off at (withing several minutes of that time)
what happens is sometimes it dose not go off at all (perhaps I set the alarm to go off to close to when i am setting it) this may not be a problem but other times it goes off shortly after i set it and it will go off twice within 0-1 seconds apart that 1-2 minutes later it will go off again at the correct time it was set to go off at.
from what i observed so far it is always one of the three scenarios:
goes off at the correct time.
goes off not at all.
goes off three times, twice right away (1-2 minutes before the scheduled time) and than a third time at the correct time.
What am i doing wrong? how can I get the alarm to go off once at approximately the right time
UPDATE:
ok so... first of all I changed changed the line that sets up the timer from:
DateTime set_for = DateTime.now().minusDays(10).withTimeAtStartOfDay().withHourOfDay(14).
withMinuteOfHour(34).withSecondOfMinute(0).
withMillisOfSecond(0);
to
DateTime set_for = DateTime.now().plusMinutes(5).withSecondOfMinute(0).withMillisOfSecond(0);
so that it will go off exactly 5 minutes from when i set it and i can make multiple test without re running the app. I was concerned I was setting the alarm to close to when i set it up.
Something to remember is the AlarmManager bunches the alarms up and fires them at the same time if they are close together (with the setRepeating method not setExact), this is to save batteries and no wake the phone up every minute or two.
i did the test with the above code and it started to work more normally. set up 4 alarms 1 minute apart, 3 of them went off at the same tome when the 3rd one was supposed to go off (which is correct behavior because they get bunched up to one to save batteries) and the last one went off very late 3-5 minutes after it was supposed to (which is fine, no problem).
So perhaps the problem is after i canceled an alarm and start a new one the AlarmManager is getting confused (when i was setting the alarm before, to close to when i set it up) and trying to group the canceled one and the one that is supposed to go off and making the not canceled one go off twice? sounds odd but perhaps Alarm are somewhat bugged???
Ok Im not 100% sure why the alarm was triggering the same one three times, but when i give more time for the alarm to run (say 5 minutes in the future apposed to 3 minutes), giving it more time seemed to solve lot of problems. feeling a little silly now for not giving it more time in the first place but every test takes 5 minutes to run, lots of waiting, which is annoying but works better now.
in the post:
setRepeating() of AlarmManager repeats after 1 minute no matter what the time is set (5 seconds in this case, API 18+)
it is mentioned:
"As of I think Android 5.1 (API version 22) there is a minimum period of 1 minute for repeating alarms, and alarms cannot be set less than 5 seconds in the future"
I was definitely within that time(or not within that time rather, more that 5 seconds), but increasing the alarm set further in the future fixed my issue.
UPDATE: during testing I set my initial timer time to several days in the past, I have noticed that if it passed the interval even if the timer was not set than it will trigger a notification as several times as it passed those intervals from the time it was set from even if the alarm was not actually set at or before that time, so that's why i was getting those extra notifications, i assume there is a limit of 2 alarms (with the same requestCode) that it can go off like this.

Getting location by few ways in Timer

Hello I'm creating tracking app and I want to quickly get the location. But this app should be friendly for people. It should works like that:
I turn on GPS and i want to get location by it
If it takes more that 5 seconds I try get location by network provider
If it takes more that 5 seconds i try to get location by wifi
if it takes more I do something else.
I already have this functions! How to do that they work one after another (If one wokrs more than 5 sec we move to another one).
So I'm thinking that I must use some kind of timer, but here I got a problem if I put code like this
Timer timer2 = new Timer();
TimerTask testing = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "test", Toast.LENGTH_SHORT).show();
}
});
}
}; timer2.schedule(testing, 1000); ***
*** here syntax errors
not inside onCreate I have syntax errors (and I want to do that after pushing the button). However how should looks this timer for 3 methods following next by next ?
depending on the OS that you are devlopping for, I would recommend you to make use of the OS specific methods available for retrieving location.
In case of Android for example there is a service available that makes is quite easy for you to retrieve the location in an user friendly manner:
Please check this: https://developer.android.com/training/location/index.html
This allows you to create location requests, depending on your situation you can define the request with a certain priority. For example: in case city precision is enough in your situation, you can define it and the framework might decide to only use the currently available WIFI to get the location (and not startup the GPS).

LocationListener with Thread.Sleep

My application uses a progress dialog to let my user know that the location listener is currently searching for their current coordinates as shown:
ProgressDialog searching;
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new GPSLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
0, locationListener);
searching = ProgressDialog.show(this, null, "Gaining GPS posistion...", false,true);
This is great but I want to set a time limit that this can run for. Can i use a simple Thread.Sleep static instance set at - for example - 20 seconds? This will then check if my location object is still null and will then cancel the search?
Can i run both a Location Listener and a thread.sleep concurrently? I have looked at the Oracle notes for Thread.Sleep but I'm still not 100% sure.
Can i use a simple Thread.Sleep static instance set at - for example - 20 seconds?
That would be disastrous. Do not use sleep() on the main application thread in Android, as it freezes your UI for however long your sleep() call is set for.
There are many better ways to get control in your activity in 20 seconds. The lightest-weight solution is to call postDelayed() on one of your widgets, with a Runnable that will execute what you want in 20 seconds.
I have looked at the Oracle notes for Thread.Sleep but I'm still not 100% sure.
Since Oracle has little to do with Android, you are better served reading Android documentation.

How to get gps coordinates every minute in Android?

I want to get my coordinates every minute, even if a user is not moving. So i used requestLocationUpdates with the following parameters:
locMgr.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
60000, // minTime in ms
0, // minDistance in meters
PosljiLokacijo.this);
But when i test it on my HTC Hero (2.1 Android) and i am not moving, onLocationChanged() is never called. If i change minDistance to 1, then i get a few updates at start but after that, they come in very unregular intervals.
How should i choose these 2 parameters (minTime and minDistance) to receive coordinates every minute?
I don't think "minTime" or "minDistance" will help in this case, unless: save the last location into variables and output them every minute. Let the locationManager overwrite those variables so after a minute, the location change becomes visible. That way there's no need to wait for an update as your variables always hold the actual position.
You can also retrieve the location from the locationManager and request the location again after one minute (or whatever you'd like your interval to be) without using requestLocationUpdates.
e.g. take a look at the Timer to set a repeated call to your method that gets the location:
http://developer.android.com/reference/java/util/Timer.html
That way you should also save battery as the system won't be looking for updates all the time.
According to the documentation:
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.
The only way I see to do what you want would be to set minTime to 0 and throw out values that are too frequent. You'd still not be guaranteed to get updates as often as you'd like, and be prepared for your app to be a battery killer as well.

Specify intervals for Location Manager to broadcast current location in Android

Is there any way to specify the time intervals that the Location Manager broadcasts the current location?
I am using a method called startListening:
public void startListening() {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
0,
0,
this
);
}
Thanks
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener, Looper looper)
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 supplied Looper is used to implement the callback mechanism.
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 whose onLocationChanged(Location)
method will be called for each
location update
looper a Looper
object whose message queue will be
used to implement the callback
mechanism.
Throws
IllegalArgumentException if provider is null or doesn't exist
IllegalArgumentException if listener is null
IllegalArgumentException if looper is null
SecurityException if no suitable permission is present for the provider.
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
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 9000, 500,locListener);
// 60000 Is 1 Minute and 100 is KM
Above you have 9000 (Nine Seconds) and 500 which is if the location has moved more than 500KM

Categories