I'd like to add a repititive taksk to a Service in my Android app. I've read about Runnable/Handler constructs, and about the Timer.scheduleAtFixedRate(). I'm wondering which one is the best approach.
I'm especially worried about the "scheduleAtFixedRate()" being run multiple times at once if execution takes longer than the interval. Or is that not possible?
How long is the interval? For this purpose, i think is good to use android AlarmManager.
It is for scheduling events on android, you can see a nice example here. And you can choose the method setRepeating instead set for repetive events.
static final long DELAY = 4000;
TimerTask task= new TimerTask (){
public void run(){
//do what you needs.
timer.shedule(this, DELAY);
}
}
Timer timer = new Timer();
timer.shedule(task, 0);
You can try this.
Related
What I want to do:
I am wanting to use a worker-thread to regularly update a textfield in the UI Thread. Let's say, every 2 seconds for 30 seconds. I need the 30 second countdown to happen even if the app is not on the foreground. For now, I am evaluating the merits of two different approaches (both using worker-threads) in implementing this. I won't post the full code here to simplify things and also because I am not asking to find any problem in my code. Both solutions work fine.
Solution #1 - use Thread.sleep() inside a for loop
for (int i = 30; i > 0; i-=2) {
Message msg = mHandler.obtainMessage(MSG_ID, i, 0);
msg.sendToTarget();
try {
Thread.sleep(2000);
} catch(Throwable t) {
// catch error
}
}
Solution #2 - use CountDownTimer
Looper.prepare()
new CountDownTimer(30000, 2000) {
public void onTick(long millUntilFinish) {
int seconds = (int)(millUntilFinish);
Message msg = mHandler.obtainMessage(MSG_ID, seconds, 0);
msg.sendToTarget();
}
public void onFinish() {
// left blank for now
}
}.start();
Looper.loop();
My Question
While both work, I am wanting to know if there is a "better" or a "preferred" way to do it for whatever reason. I am thinking there may be areas particularly in battery life but also in performance, accuracy or code design where one solution is better than the other.
What I have done so far to answer this question
My own evaluation so far from reading this SO question and CountDownTimer's documentation are that since both are executed on the worker-thread, both have no ANR possibility. Both solutions will also gaurantee that one "update" will happen only after the previous update has finished. Unfortunately, this is all I have and hoping if anyone can help or guide me to an insightful and/or similar SO question I may have overlooked or was unsuccessful in finding.
I write this question a bit cautiously as I don't have a problematic code which requires debugging but I think this falls within SO's category of a "specific programming problem", which hasn't been answered, and not included in the list of off-topic answers.
1.Calling Thread.sleep pauses the thread execution for a while where as countdown timer actually uses callbacks to notify timer expiry events and is asynchronous in nature.
2.If the thread execution pauses, you will not be able to use that specific thread for any other operation until the sleep timeout hence it is not recommended to use Thread.sleep approach. Obviously there is a load on cpu if it has to resume the thread execution and pause it.Where as in the case of countdown timer the thread continue to be in execution/idle state and as when events occur it fires to the respective listeners.
call Thread.sleep() method is not good idea beacuse ii sleep the UI Thread and disadvantage of CountDownTimer is, It Will stop when ur screen is off hence instead of this two try Handler for that like this
Handler handler;
Runnable runnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run()
{
if (dataReceived)
{
cancelHandler();
}
}
};
handler.postDelayed(runnable, 100);
}
public void cancelHandler()
{
handler.removeCallbacks(runnable);
}
in the beginning I thought it would be fairly simple, but I guess it's not.
I want to call a URL every 10 minutes, either when the app is in the background or
in the foreground. How can I realize this?
I'd use a Service with a Handler inside. Using directly Threads is another approach but it's more likely it will be killed if the Android OS needs to free memory.
The Handler part would be something like this:
boolean stopHandler = false;
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do whatever you need
...
if (!stopHandler) {
handler.postDelayed(this, 600000); // 10 minutes
}
}
};
In iOS 7 you can schedule background operations for periodically fetching data from the network. This tutorial is an example of scheduling background fetch operations -
I want to programm a game for Android.
Play principle: The user should have a short time to choose the correct answer.
My problem is the combination between the input (choosing the answer) and the time (countdown). I tried to run a thread, but the thread isn't stoppable. So the user gives the answer, the next activity will be shown and after a while (when the "timer" becomes 0) the activity will be shown again.
How could I implement this in a correct way?
Should I use Thread, Handler, CountDownTimer ?
You can keep a running timer using this on init:
Timer updateTimer = new Timer("update");
updateTimer.scheduleAtFixedRate(new TimerTask() {
public void run() {
updateGUI();
}
}, 0, 1000);
long startTime = System.currentTimeMillis();
Then in a Thread:
//Clock update
currentTime = System.currentTimeMillis() - startTime;
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
clock.setText(sdf.format(currentTime));
clock.invalidate();
You could stop the Thread with a boolean inside or outside as you please?
Okay, I don't know the specific libraries to use, and I haven't done any thread programming myself, but I would think of the program as a state machine. I hope it helps :/
Set up a boolean userHasAnswered = false.
Set up a specialized listener (e.g. touch listener for some button) for answers.
If the listener gets an appropriate response from the user, set userHasAnswered = true.
When question loads up, start the thread which counts down.
If user fails to give ans when the time reaches zero, just call loadNextQuestion().
In your thread, do periodic checks every few units of time to see if userHasAnswered == true, and if it is true, then call updateScore() and loadNextQuestion().
You may want to have a look at alarm manager
My problem is similar to this one, How to update a widget every minute, however I only want to update TextView of the UI. I need access to the time so unfortunately can not simply use the DigitalClock view.
Ive been researching and have found ways to update every minute, but not on the minute so they are synchronised with the system clock (so they might be up to 59 seconds out of sync!)
The only ways I can think to do it are
(a) Run a handler (or timer) every second (which seems a bit like overkill if I only want to update every minute) Like this from the android.com resources
(b) Have a service running in background. (I'm not keen on this as I already have more important things running in the background)
(c) use Alarm Manager (again seems like overkill)
Seems to be such an easy thing to do, and yet...
Any advice appreciated
Mel
The accepted answer does not respond specifically to the question. The OP asks for a way to receive some sort of event on time (at the system clock minute and 00 seconds).
Using a Timer is not the right way to do this. It's not only overkill, but you must resort to some tricks to make it right.
The right way to do this (ie. update a TextView showing the time as HH:mm) is to use BroadcastReceiver like this :
BroadcastReceiver _broadcastReceiver;
private final SimpleDateFormat _sdfWatchTime = new SimpleDateFormat("HH:mm");
private TextView _tvTime;
#Override
public void onStart() {
super.onStart();
_broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().compareTo(Intent.ACTION_TIME_TICK) == 0)
_tvTime.setText(_sdfWatchTime.format(new Date()));
}
};
registerReceiver(_broadcastReceiver, new IntentFilter(Intent.ACTION_TIME_TICK));
}
#Override
public void onStop() {
super.onStop();
if (_broadcastReceiver != null)
unregisterReceiver(_broadcastReceiver);
}
The system will send this broadcast event at the exact beginning of every minutes based on system clock. Don't forget however to initialize your TextView beforehand (to current system time) since it is likely you will pop your UI in the middle of a minute and the TextView won't be updated until the next minute happens.
You can try configuring a Timer to run a TimerTask that updates your TextView every minute (see its schedule method).
have you tried postDelayed()
This is what I used :
int secsUntilOnTheMinute=60-Calendar.getInstance().get(Calendar.SECOND);
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
updateSendTimesHandler.sendEmptyMessage(0);
}
}, secsUntilOnTheMinute*1000, 60000);
I need to write a helper method which I can use in various places in the app to essentially make it 'sleep' for N milliseconds.It looks like Handler.postAtTime may be one way to do it, but I'd like any code snippets if available.
You did not say why you need your app to "sleep".
Assuming you need to run a task after some time:
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
// do something here
}
}, 1000); // 1000 ms delay
If you don't mind blocking the thread, an alternative to Thread.sleep() is SystemClock.sleep().
Benefit is that it's a one-liner, as it ignores the
InterruptedException so you don't need to handle it.
More info on http://developer.android.com/reference/android/os/SystemClock.html.
As already stated, you should avoid calling this on the main UI thread as it will cause your app to become unresponsive and potentially show the dreaded dialog we all hate to see (please wait or force close.)
Are you looking for something like this?
try {
//Put the thread to sleep for the desired amount of time (milliseconds)
Thread.currentThread().sleep(1000);
}
catch(InterruptedException ie){
}
This will put the thread you are calling it from to sleep for the amount of time you specify.