I have used Countdown Timer like this
new CountDownTimer(15000, 15) {
public void onTick(long millisUntilFinished) {
long seconds=millisUntilFinished/1000;
long min=millisUntilFinished%100;
timeleft=(int) (seconds*1000+min);
if(millisUntilFinished>=10000)
{
changeText.setTextColor(Color.GREEN);
}
else if(millisUntilFinished>=5000)
{
changeText.setTextColor(Color.MAGENTA);
}
else
{
changeText.setTextColor(Color.RED);
}
changeText.setText(String.format("%02d", seconds )+ "."+String.format("%02d", min )+" sec");
}
public void onFinish() {
timeleft=0;
missed++;
nametext.setTextColor(Color.RED);
nametext.setText("Time Up!");
bottombutton.setVisibility(View.INVISIBLE);
globalflag=13;
changeText.setTextColor(Color.RED);
changeText.setText("0.00 Sec");
Handler myHandler = new Handler();
myHandler.postDelayed(mMyRunnablecif, 3000);
}
}.start();
On a button click I have called cancel() but it stops counting for a while and then calls onFinish(). I need not to call onFinish() after calling cancel(). Is there any solution for this. Any help will be highly appreciated.
Inside your onClick set a Boolean (buttonPressed for example) to true.
In your onFinish check this Boolean:
if (buttonPressed == true)
{
//do nothing
}
else
{
//run code
}
You could use Timer instead and do something like this:
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
// do your updates here
mUpdateTimeHandler.postDelayed(this, 1000);
}
};
Handler mUpdateTimeHandler = new Handler();
mUpdateTimeHandler.postDelayed(mUpdateTimeTask, 100);
When cancelling the task:
mUpdateTimeHandler.removeCallbacks(mUpdateTimeTask);
I also don't understand why the onFinish gets called despite calling cancel(). I guess the only workaround for this is to just null check your calls in onFinish to prevent any NPE's.
public void onFinish() {
if (nametext == null || bottombutton == null || changeText == null || ... ) {
return;
}
...
Related
I need to update a TextView frequently with a specific time delay in the android studio. The code is below. Thank you.
Edit: I also need to end the loop with a button click or with an "if" control.
//INFLATION CALCULATION !!!
/**
* This method calculates Inflation value.
*/
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
}
}, delay*12);
}
Call the same method inside the runnable in order to keep the loop going
Use a flag in order to be able to stop the loop: shouldCalculate
private boolean shouldCalculate = true; // set to false when you want to end the loop
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (shouldCalculate) {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
calculateInflation();
}
}
}, delay*12);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
customHandler.postDelayed(this, 0);
}
};
public void startTimer() {
//timer
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public void stopTimer() {
//timer stops
customHandler.removeCallbacks(updateTimerThread);
//timer ends
}
make a reference of runnable thread , start it using startTimer() and remove thread using stopTimer() as you said on a button click or up on a specific conditions .Also you can change the postDelayed milliseconds as ur wish
Try below code. This will do the trick. If you find any problem please let me know.
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
if(shouldRepeat)
calculateInflation();
}
}, delay*12);
}
And second approach can be CountDownTimer. Make a method as shown in below code
public void timerTask(final int loopTime){
//Loop time is the actual time for repeatation
new CountDownTimer(loopTime, 1000) {
public void onTick(long millisUntilFinished) {
//this tells you one second is passed
}
public void onFinish() {
//here on time finish you need to define your task
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
//call the same method again for looping
timerTask(loopTime);
}
}.start();
}
Simplest way. Here updateRunnable calls itself with delay. Make updateRunnable as global variable to access from anywhere.
Runnable updateRunnable = new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
handler.postDelayed(this, UPDATE_TIME);
}
};
Start handler. Here we start handler immediately without delay.
handler.postDelayed(updateRunnable, 0)
Stop handler
handler.removeCallbacks(updateRunnable)
By the way don't forget to stop handler on onDestroy()
Here is my Method i want to check a that a circle lies on the button for five seconds for this i have used a runnable.but a problem is that i want to check it every second that the position of the circle changes or not if the circle position have been changes then start the handler timer from start for the new position otherwise call the method
private Runnable createRunnable(int paramPosition)
{
Runnable aRunnable = new Runnable()
{
public void run()
{
handler.postDelayed(this, 1000);
if (numOfSeconds == 5)
{
handler.removeCallbacks(this);
numOfSeconds = 0;
if (paramPosition == circlePosition)
{
methodCall(paramPosition);
handler.removeCallbacks(this);
}
else
{
if (paramPosition == circlePosition)
{
numOfSeconds++;
}
else
{
numOfSeconds = 0;
}
handler.postDelayed(this, 5000);
}
}
}
return aRunnable;
};
}
so how i can perform this work please suggest a method to solve this problem.
thanks
I'm designing a game and have a problem with countdowntimer not stopping. The timer starts normally as it should, and should stop in the end() method. It works well when ENEMY_HULL is checked as 0 or less, which is calulated seperatly when the users presses a button, and checkEnemyDefeat() is called, but it does not work when ENEMY_CREW is 0. On both situations the message in log cat that the timer is stopped appears, so my guess is that .cancel() is called. I've included all code that seems relevant.
NOTE: All variables including CountDownTimer are global variables
Here is the method containing the timer:
private void BadGameLoop() {
if (GAME_PAUSED == true && !GAME_TIME_STARTED) {
Log.d(" -------- ", "TIMER STARTED");
GAME_PAUSED = false;
GAME_TIME_STARTED = true;
gameTimer = new CountDownTimer(GAME_TIME, UPDATE_RATE) {
#Override
public void onTick(long millisUntilFinished) {
TICKS++;
timer.setText(String.valueOf(GAME_TIME / 1000 - TICKS / 10));
if((CREW_BOARDING > 0 || ENEMY_CREW_BOARDING > 0) && TICKS%10 == 0){
crewFightCalculator();
}
updateViews();
}
#Override
public void onFinish() {
TICKS=0;
GAME_TIME_STARTED = false;
GAME_PAUSED = true;
end();
}
};gameTimer.start();
}
}
Next is the crewFightCalculator method:
private void crewFightCalculator(){
// this just changes the values of ENEMY_CREW (global variable) and then
//calls checkEnemyDefeat() to verify if it should end the timer or not
checkEnemyDefeat();
}
The checkEnemyDefeat and end methods:
private void checkEnemyDefeat(){
if(ENEMY_HULL <= 0){
updateViews();
end();
}else if ( ENEMY_CREW < 1){
updateViews();
end();
}
}
private void end(){
if(GAME_TIME_STARTED){
GAME_TIME_STARTED = false;
gameTimer.cancel();
Log.d("---------"," TIMER STOPPED !");
}
// do more stuff
}
It is simply bizzare to me why it dosen't work. My only guess is that it has something to do with the fact that .cancel() is not triggered by a chain of functions started by user input .
The only solution to this problem that I found, was to modify the onTick method, so that it should check every time if it should run or stop the timer like this:
private void BadGameLoop() {
if (GAME_PAUSED == true && !GAME_TIME_STARTED) {
Log.d(" -------- ", "TIMER STARTED");
GAME_PAUSED = false;
GAME_TIME_STARTED = true;
gameTimer = new CountDownTimer(GAME_TIME, UPDATE_RATE) {
#Override
public void onTick(long millisUntilFinished) {
if(GAME_TIME_STARTED) {
TICKS++;
timer.setText(String.valueOf(GAME_TIME / 1000 - TICKS / 10));
if((CREW_BOARDING > 0 || ENEMY_CREW_BOARDING > 0) && TICKS%10 == 0){
crewFightCalculator();
}
updateViews();
}else{
gameTimer.cancel();
}}
#Override
public void onFinish() {
TICKS=0;
GAME_TIME_STARTED = false;
GAME_PAUSED = true;
end();
}
};gameTimer.start();
}
}
Still, i can't figure out why it didn't work properly before.
Wherever I've seen use of asynctask , it is used for downloading or operation that returns some results. But What if i just want to set a time to time updation of my TextView in activity and do some work at the end .
But at the same time How can i cancel asynctask operation from activity so its onPostExecute , do not run .Like when back button is pressed from activity. Any clues ?
[UPDATE]
For Time to time updation i mean:
TextView tv = findViewById(R.id.disco);
try{
for(int i=0;i<10000;i++){
Thread.sleep();
tv.setText(" "+i);
}
}
catch(Exception e){}
/* i know i can achieve finally in onPostExecute but what if i want to cancel it during runtime*/
finally{
// do some more operations after execution
}
Done it myself after some brain storming and searching , i am using CountDownTimer.
in OnCreate():
counter = new CountDownTimer((PROGRESSSECONDS+1)*1000,1000) {
int collapsed = 0;
#Override
public void onTick(long millisUntilFinished) {
collapsed++;
pb.setProgress(collapsed);
}
#Override
public void onFinish() {
Intent in = new Intent(FirstActivity.this,PointsDrawerActivity.class);
startActivity(in);
}
};
counter.start();
in onBackPressed():
#Override
public void onBackPressed() {
counter.cancel();
counter = null;
setContentView(R.layout.activity_first);
}
it worked.
Handler is optimum for your requirement
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
callMethod();
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
and in order to cancel an ongoing AsyncTask the official docs says it all
A task can be cancelled at any time by invoking cancel(boolean).
Invoking this method will cause subsequent calls to isCancelled() to
return true.
After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[])
returns.
To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically
from doInBackground(Object[]), if possible (inside a loop for
instance.)
Ex: MyTask.cancel(true);
You should use timer task rather than Async task here.
Here is sample:
private TimerTask timerTask;
int i = 0;
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
//Do your text view update here.
tv.setText(" "+ (i++));
}
});
}
};
In your onResume() do like:
private Timer timer;
public void onResume() {
timer = new Timer();
timer.schedule(timerTask, 1000); // time in milliseconds, you can set accordingly requirement.
}
And onPause() you can stop it by:
public void onPause() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
I have tried multiple ways to have a single persistent timer update the ui in multiple activities, and nothing seems to work. I have tried an AsyncTask, a Handler, and a CountDownTimer. The code below does not execute the first Log.i statement.... Is there a better way to start the timer (which must be called from another class) in Main (which is the only persistent class)?
public static void MainLawTimer()
{
MainActivity.lawTimer = new CountDownTimer(MainActivity.timeLeft, 1000)
{
public void onTick(long millisUntilFinished)
{
Log.i("aaa","Timer running. Time left: "+MainActivity.timeLeft);
MainActivity.timeLeft--;
if(MainActivity.timeLeft<=0)
{
//do stuff
}
else
{
//call method in another class
}
}
public void onFinish()
{ }
}.start();
}
To clarify my problem:
When I run the code the Log.i("aaa","Timer running") statement is never shown in the log, and the CountDownTimer never seems to start. MainLawTimer is called from another class only (not within the same class.
For CountDownTimer
http://developer.android.com/reference/android/os/CountDownTimer.html
You can use a Handler
Handler m_handler;
Runnable m_handlerTask ;
int timeleft=100;
m_handler = new Handler();
#Override
public void run() {
if(timeleft>=0)
{
// do stuff
Log.i("timeleft",""+timeleft);
timeleft--;
}
else
{
m_handler.removeCallbacks(m_handlerTask); // cancel run
}
m_handler.postDelayed(m_handlerTask, 1000);
}
};
m_handlerTask.run();
Timer
int timeleft=100;
Timer _t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
Log.i("timeleft",""+timeleft);
//update ui
}
});
if(timeleft>==0)
{
timeleft--;
}
else
{
_t.cancel();
}
}
}, 1000, 1000 );
You can use a AsyncTask or a Timer or a CountDownTimer.
Thank you all for your help, I discovered the error in my code... timeLeft was in seconds rather then milliseconds. Since timeLeft was under 1000 (the wait period) the timer never started.