Running for loop periodically - android

I want to run a for loop every 5 minutes for an Android application. Is there a better method than this where less processing is done
for(;;) {
// code
final long NANOSEC_PER_SEC = 1000 * 1000 * 1000;
long startTime = System.nanoTime();
while ((System.nanoTime() - startTime) < 5 * 60 * NANOSEC_PER_SEC) {
}
}

CountDownTimer is a good class for this kind of work. It looks like this:
long duration = 12345;
long ticksInterval = 5000; // 5 second in millis
new CountDownTimer(duration, ticksInterval){
public void onTick(long remaining) {
// Do something each ticksInterval millis
}
public void onFinish() {
// Do something after duration millis
}
}.start();
That said, I don't think you can use this for an infinite amount of time since it requires an ending time. Though you can hack to restart it once it's finished.

You should go for set Repeat Alert for every 5 Minute and Run your code inside that .
Also you can go for use of Handler like below code .
final int REPEAT_CALL=2;
final int mFIVE_MINUTE=5*60*1000;
private Handler mHandler=new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case REPEAT_CALL:
//This will get execute by every 5 minute so write you for loop code here.
mHandler.sendEmptyMessageDelayed(REPEAT_CALL,mFIVE_MINUTE);
break;
}
}
};
You can start it by calling this :
mHandler.sendEmptyMessageDelayed(REPEAT_CALL,10);
Then after it will call by every 5 minute .
You can cancel this call back by calling below method:
mHandler.removeMessages(REPEAT_CALL);

Related

Automatically refresh image every 2 seconds android

So I am trying to have a picture automatically refresh every 2 seconds. I've tried the handler/timer method, but I'm confused as how to call it and for some reason can not get it to actually refresh...
private void refreshPicture(final String refreshRate, final String userName, final String userPicture) {
final Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = Long.parseLong(refreshRate);
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
//my method where i refresh image
getUserPicture(userName, userPicture);
timerHandler.postDelayed(this, 500);
}
};
}
You forgot to initiate the first call of the runnable. After defining the timerRunnable, you have to call timerHandler.post(timerRunnable); once. Also, if you want to have it refreshed every 2 seconds, you have to put 2000 instead of 500 as value in postDelayed().
Don’t forget to call timerHandler.removeCallbacks(timerRunnable) when you want to stop refreshing.

Starting Two (or More) Functions Simultaneously in Android

I'm in the process of designing a chronometer / countdown timer app for Android 2.2 and would like one button press to start both the chronometer and the timer simultaneously. So, ideally, I'd like the seconds (time) on both the chronometer and timer to change at the same instance. (The timer will be counting down even as the chronometer is counting up). Since I'm using the chronometer and timer functionality provided by Android, I wrote the following piece of code when the user presses the 'Start' button
private boolean mStartPressedOnce = false;
long mTimeWhenStopped = 0;
Chronometer mChronometer;
MyCounter mCounter;
...
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.StartButton:
// Perform some initialization for the chronometer depending
// on the button press
if (mStartPressedOnce == false) {
mChronometer.setBase(SystemClock.elapsedRealtime());
} else {
mChronometer.setBase(SystemClock.elapsedRealtime() + mTimeWhenStopped);
}
// Perform the initialization for the timer
mCounter = new MyCount(45000, 1000);
// Fire up the chronometer
mChronometer.start();
// Fire up the timer
mCounter.start();
break;
case R.id.ResetButton:
// Reset the chronometer
mChronometer.setBase(SystemClock.elapsedRealtime());
mTimeWhenStopped = 0;
break;
case case R.id.StopButton:
mStartPressedOnce = true;
// Stop the chronometer
mTimeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime();
mChronometer.stop();
break;
}
...
public class MyCounter extends CountDownTimer {
#Override
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
// Nothing to do here
}
#Override
public void onTick(long millisUntilFinished) {
long seconds = (long) (millisUntilFinished / 1000);
long minutes = (long) ((millisUntilFinished / 1000) / 60);
long hours = (long) (((millisUntilFinished / 1000) / 60) / 60);
// Do some formatting to make seconds, minutes and hours look pretty
// Update the timer TextView
(TextView) findViewById(R.id.CountDownTimerTextView))
.setText(hours + ":" + minutes + ":" + seconds);
}
}
Though it looks like the seconds on the chronometer and timer are in sync initially, after a short time, they seem to go off and the second updates for both occur at different times.
Was wondering what I could do to fix this. I did come across - and read this thread
Running multiple AsyncTasks at the same time -- not possible?
I realize that there may be a design change needed but I'm not sure exactly what needs to be done.
Edit: Included types for chronometer and timer and method for calculating time using Chronometer - per jolivier and njzk2's suggestions
You can retrieve the current time with System.currentTimeMillis(), store it into a variable and forward it to both mChronometer and mCounter, so that they use the same time reference although their task started at different time.
Edit: with the given types, the android documentation about Chronometer will tell you that you can use elapsedRealTime to achieve what I said.
CountDownTimer does not have this and its start method is final so you may want to use another implementation, a better view of your use case might help us.
Basically, wanting two threads to perform an action at the same millisecond is never a good idea, one of them will serve as the clock and the other one must be a slave and listen to the clock.
So, after mulling over this for some time and going off of the suggestion jolivier so generously shared with us, I realized that there exists a method called onChronometerTick which is called every time there is chronometer tick (every second, in this case). So, I thought of subtracting 1000 milliseconds from the counter every time the method is called and update the timer display accordingly. I got rid of the Android timer piece (CountDownTimer) completely. I figured this would be a nice way to have both displays update at the same time. It's also a simple implementation of a timer.
I'm happy to report that it seems to work well. Both the timer and chronometer displays indeed update at the same time. So, the original question looks like it's answered. Unfortunately, I ran into an off-by-two error on the timer front that I fixed with an ugly hack. I'm posting what I have so far. Any suggestions on how to fix the hack or improve the code are welcome. Note that I have commented the code to try to make it easy to understand what's been done.
Edit for bug: One more thing I noticed is that after around 10 minutes or so the chronometer and timer are off by one second. More precisely, the timer is behind the chronometer by one second. Not yet sure why this happens.
private boolean mStartPressedOnce = false;
long mTimeWhenStopped = 0;
Chronometer mChronometer;
long millisUntilFinished = 0;
boolean firstPassOver = false;
int counter = 0;
...
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.StartButton:
// Perform some initialization for the chronometer depending
// on the button press
if (mStartPressedOnce == false) {
mChronometer.setBase(SystemClock.elapsedRealtime());
} else {
mChronometer.setBase(SystemClock.elapsedRealtime() + mTimeWhenStopped);
}
// Fire up the chronometer
mChronometer.start();
break;
case R.id.ResetButton:
// Reset the chronometer
mChronometer.setBase(SystemClock.elapsedRealtime());
mTimeWhenStopped = 0;
break;
case case R.id.StopButton:
mStartPressedOnce = true;
// Stop the chronometer
mTimeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime();
mChronometer.stop();
break;
}
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stop_watch);
mChronometer = (Chronometer) findViewById(R.id.StopWatchTextView);
// Initialize the number of milliseconds before the timer expires (
// set the timer) - in this case to 46 seconds
millisUntilFinished = 46000;
// Display how many seconds remain before the timer expires
((TextView) findViewById(R.id.CountDownTimerTextView)).setText(hours
+ ":" + minutes + ":" + millisUntilFinished / 1000);
// In line with the suggestion provided by jolivier - make the timer
// the slave and update its display every time the chronometer
// ticks
mChronometer
.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
#Override
public void onChronometerTick(Chronometer chronometer) {
// Update the display for the chronometer
CharSequence text = chronometer.getText();
chronometer.setText(text);
// Update the display for the timer
// !!! BUG !!!
// Looks like onChronometerTick is called at the 0th second
// and this causes an off by two error if a count down timer
// is being implemented. Fixed it with this hack. There's gotta
// be a more elegant solution, though.
if(counter >= 2) {
millisUntilFinished1 = millisUntilFinished1 - 1000;
counter = 2;
}
counter++;
if (millisUntilFinished >= 0) {
long seconds = (long) (millisUntilFinished / 1000);
long minutes = (long) ((millisUntilFinished / 1000) / 60);
long hours = (long) (((millisUntilFinished / 1000) / 60) / 60);
// Do some formatting to make seconds, minutes and hours look pretty
// Update the timer TextView
((TextView) findViewById(R.id.CountDownTimerTextView))
.setText(hours + ":" + minutes + ":"
+ seconds);
}
}
});
// Other code
...
}

android CountDownTimer - last onTick not called - what clean solution to use?

frustration post ....
I just stumbled into the "CountDownTimer - last onTick not called" problem many have reported here.
Simple demo showing the problem
package com.example.gosh;
import android.app.Activity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
public class CountDownTimerSucksActivity extends Activity {
int iDontWantThis = 0; // choose 100 and it works yet ...
private static final String TAG = "CountDownTimerSucksActivity";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new MyCountDownTimer(10000 + iDontWantThis , 1000).start();
}
class MyCountDownTimer extends CountDownTimer {
long startSec;
public MyCountDownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
// TODO Auto-generated constructor stub
startSec = System.currentTimeMillis() ;
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
Log.e(TAG, " onFinish (" + getSeconds() + ")");
}
#Override
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
Log.e(TAG, millisUntilFinished + " millisUntilFinished" + " (" + getSeconds() + ")");
}
protected long getSeconds() {
return (((System.currentTimeMillis() - startSec) / 1000) % 60);
}
}
}
The logcat output from a test run ...
As you can see the last call onTick is happening with 1963ms millisUntilFinished, then the next call is onFinished nearly 2 seconds later. Surely a buggy behavior. I found many posts on this yet no clean solution yet. One I included in the source code, if you set the iDontWantThis field to 100 it works.
I dont mind workarounds in minor fields yet this seems such a core functionality that i cant fathom it wasnt fixed yet. What are you people doing to have a clean solution for this?
Thanks a lot
martin
UPDATE:
A very useful modification of the CountDownTimer by Sam which does not surpresses the last tick due to internal ms delay and also prevents the accumulation of ms delay with each tick over time can be found here
The behavior you are experiencing is actually explicitly defined in the CountdownTimer code; have a look at the source.
Notice inside of handleMessage(), if the time remaining is less than the interval, it explicitly does not call onTick() and just delays until complete.
Notice, though, from the source that CountdownTimer is just a very thin wrapper on Handler, which is the real timing component of the Android framework. As a workaround, you could very easily create your own timer from this source (less than 150 lines) and remove this restriction to get your final tick callback.
I think the frustration comes from an incorrect expectation of what a tick should be. As the other answer noted, this behavior is intentional. Another possible way of handling this is to simply specify a smaller interval. If you were implementing some sort of countdown clock for example, it wouldn't hurt to change the interval to 500. If it's important that some work is only done when the seconds change, then you can do that too by storing the result of getSeconds() and only doing that work when that value changes.
If CountdownTimer were changed to always fire that last tick even if the remaining time is less than the interval, I'm sure StackOverflow would have a bunch of questions like "why do I not have enough time in the last tick of CountdownTimer?"
I don't understand why you say that it is intentional behaviour, the API says exactly:
"Schedule a countdown until a time in the future, with regular notifications on intervals along the way."
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
if you set the time to 30 seconds, and the countDownInterval to 1000, as the API says regular, it should be fired exactly 30 times.
I think it's not an intentional behaviour but a wrong implementation.
The solution should be the one proposed by Sam here:
android CountDownTimer - additional milliseconds delay between ticks
Android's CountDownTimer calls onTick() for the first time as soon as (without delay) the timer is started (as can be seen on line number 93)
Post this, onTick() is called based upon the time remaining until the timer is completed.
If the time remaining until timer completed is less than the time interval specified, then onTick() is not called (line number 136). This is the reason your last onTick() is not being called.
Modified CountDownTimer class
I have modified the timer to call onTick() all intervals (including first and last) after specified delay. Here is the class -
public abstract class CountDownTimer {
private final long mMillisInFuture;
private final long mCountdownInterval;
private long mStopTimeInFuture;
private boolean mCancelled = false;
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
}
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
onTick(mMillisInFuture);
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG), mCountdownInterval);
return this;
}
public abstract void onTick(long millisUntilFinished);
public abstract void onFinish();
private static final int MSG = 1;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
synchronized (CountDownTimer.this) {
if (mCancelled)
return;
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
} else {
onTick(millisLeft);
sendMessageDelayed(obtainMessage(MSG), mCountdownInterval);
}
}
}
};
}

Do an operation every 100ms for 1000 ms

I would like to do an operation every 100ms for 1000ms.
I believe I would need to use the
handler
How do I do that?
Handler h = new Handler();
int count = 0;
int delay = 100;//milli seconds
long now = 0;
h.postDelayed(new Runnable(){
public void run(){
now = System.currentTimeMillis();
//do something
if(10>count++)
h.postAtTime(this, now + delay);
},
delay};
Please note that your operation MUST take less then 100ms to execute or it will not be able to run every 100ms, this will be the case for all methods.
Timer t = new Timer();
int count = 0;
t.scheduleAtFixedRate(new TimerTask() {
count++;
// Do stuff
if (count >= 10)
t.cancel();
}, 0, 100);
This schedules a timer to execute a TimerTask, with a 0 millisecond delay. It will execute the body of the TimerTask every 100 milliseconds. Using count to keep track of where you are in the task, after 10 iterations, you may cancel the timer.
As #Jug6ernaut mentioned, ensure your task won't take long to execute. Lengthy tasks (ones that take longer than 100 milliseconds, in your case) will cause lag/potentially undesirable results.
You can do this by using a Timer.
I don't have time to test this right now, but this should work
This is one way:
Your methods you want to call from here will probably need to be static
This class can be nested in another class
You could use % (modulus) so the timer can keep counting up and you can set things to happen at more intervals
create this timer:
private Timer mTimer = new Timer();
to start this timer:
mTimer.scheduleAtFixedRate(new MyTask(), 0, 100L);
the timer class:
/**
* Nested timer to call the task
*/
private class MyTask extends TimerTask {
#Override
public void run() {
try {
counter++;
//call your method that you want to do every 100ms
if (counter == 10) {
counter = 0;
//call method you wanted every 1000ms
}
Thread.sleep(100);
} catch (Throwable t) {
//handle this - maybe by starting it back up again
}
}
}

Send a number of "Toast"s spaced by 2 seconds

I need to display 4 "Toast"s spaced by 2 seconds between them.
How do I do this in such a way that they wait for each other and that the program itself waits until the last of them has displayed?
simply use handlers.
handler has a method called sendMessageDelayed(Message msg, long delayMillis).
just schedule your messages at the interval of 2 seconds.
here is a sample code.
int i=1;
while(i<5){
Message msg=Message.obtain();
msg.what=0;
hm.sendMessageDealayed(msg, i*2);
i++;
}
now this code will call handler's method handleMessage after every 2 seconds.
here is your Handler
Handler hm = new Handler(){
public void handleMessage(Message msg)
{
//Toast code.
}
};
and you are done.
Thanks.
Handlers are definitely the way to go but I would just postDelayed instead of handling an empty message.
Also extending Toast and creating a method for showing it longer is nice.
Sample Code:
// make sure to declare a handler in the class
private final Handler mHandler = new Handler();
// The method to show longer
/**
* Show the Toast Longer by repeating it.
* Depending upon LENGTH_LONG (3.5 seconds) or LENGTH_SHORT (2 seconds)
* - The number of times to repeat will extend the length by a factor
*
* #param number of times to repeat
*/
public void showLonger(int repeat) {
// initial show
super.show();
// to keep the toast from fading in/out between each show we need to check for what Toast duration is set
int duration = this.getDuration();
if (duration == Toast.LENGTH_SHORT) {
duration = 1000;
} else if (duration == Toast.LENGTH_LONG) {
duration = 2000;
}
for (int i = 1; i <= repeat; i++) {
// show again
handler.postDelayed(new Runnable() {
#Override
public void run() {
show();
}
}, i * duration);
}
}

Categories

Resources