Timertask change TextView setText()? [duplicate] - android
Can someone give a simple example of updating a textfield every second or so?
I want to make a flying ball and need to calculate/update the ball coordinates every second, that's why I need some sort of a timer.
I don't get anything from here.
ok since this isn't cleared up yet there are 3 simple ways to handle this.
Below is an example showing all 3 and at the bottom is an example showing just the method I believe is preferable. Also remember to clean up your tasks in onPause, saving state if necessary.
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class main extends Activity {
TextView text, text2, text3;
long starttime = 0;
//this posts a message to the main thread from our timertask
//and updates the textfield
final Handler h = new Handler(new Callback() {
#Override
public boolean handleMessage(Message msg) {
long millis = System.currentTimeMillis() - starttime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
text.setText(String.format("%d:%02d", minutes, seconds));
return false;
}
});
//runs without timer be reposting self
Handler h2 = new Handler();
Runnable run = new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - starttime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
text3.setText(String.format("%d:%02d", minutes, seconds));
h2.postDelayed(this, 500);
}
};
//tells handler to send a message
class firstTask extends TimerTask {
#Override
public void run() {
h.sendEmptyMessage(0);
}
};
//tells activity to run on ui thread
class secondTask extends TimerTask {
#Override
public void run() {
main.this.runOnUiThread(new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - starttime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
text2.setText(String.format("%d:%02d", minutes, seconds));
}
});
}
};
Timer timer = new Timer();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
text = (TextView)findViewById(R.id.text);
text2 = (TextView)findViewById(R.id.text2);
text3 = (TextView)findViewById(R.id.text3);
Button b = (Button)findViewById(R.id.button);
b.setText("start");
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button b = (Button)v;
if(b.getText().equals("stop")){
timer.cancel();
timer.purge();
h2.removeCallbacks(run);
b.setText("start");
}else{
starttime = System.currentTimeMillis();
timer = new Timer();
timer.schedule(new firstTask(), 0,500);
timer.schedule(new secondTask(), 0,500);
h2.postDelayed(run, 0);
b.setText("stop");
}
}
});
}
#Override
public void onPause() {
super.onPause();
timer.cancel();
timer.purge();
h2.removeCallbacks(run);
Button b = (Button)findViewById(R.id.button);
b.setText("start");
}
}
the main thing to remember is that the UI can only be modified from the main ui thread so use a handler or activity.runOnUIThread(Runnable r);
Here is what I consider to be the preferred method.
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class TestActivity extends Activity {
TextView timerTextView;
long startTime = 0;
//runs without a timer by reposting this handler at the end of the runnable
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
timerTextView.setText(String.format("%d:%02d", minutes, seconds));
timerHandler.postDelayed(this, 500);
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_activity);
timerTextView = (TextView) findViewById(R.id.timerTextView);
Button b = (Button) findViewById(R.id.button);
b.setText("start");
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button b = (Button) v;
if (b.getText().equals("stop")) {
timerHandler.removeCallbacks(timerRunnable);
b.setText("start");
} else {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
b.setText("stop");
}
}
});
}
#Override
public void onPause() {
super.onPause();
timerHandler.removeCallbacks(timerRunnable);
Button b = (Button)findViewById(R.id.button);
b.setText("start");
}
}
It is simple!
You create new timer.
Timer timer = new Timer();
Then you extend the timer task
class UpdateBallTask extends TimerTask {
Ball myBall;
public void run() {
//calculate the new position of myBall
}
}
And then add the new task to the Timer with some update interval
final int FPS = 40;
TimerTask updateBall = new UpdateBallTask();
timer.scheduleAtFixedRate(updateBall, 0, 1000/FPS);
Disclaimer: This is not the ideal solution. This is solution using the Timer class (as asked by OP). In Android SDK, it is recommended to use the Handler class (there is example in the accepted answer).
If you also need to run your code on UI thread (and not on timer thread), take a look on the blog: http://steve.odyfamily.com/?p=12
public class myActivity extends Activity {
private Timer myTimer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 1000);
}
private void TimerMethod()
{
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//This method runs in the same thread as the UI.
//Do something to the UI thread here
}
};
}
If one just want to schedule a countdown until a time in the future with regular notifications on intervals along the way, you can use the CountDownTimer class that is available since API level 1.
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
editText.setText("Seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
editText.setText("Done");
}
}.start();
This is some simple code for a timer:
Timer timer = new Timer();
TimerTask t = new TimerTask() {
#Override
public void run() {
System.out.println("1");
}
};
timer.scheduleAtFixedRate(t,1000,1000);
I think you can do it in Rx way like:
timerSubscribe = Observable.interval(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Long>() {
#Override
public void call(Long aLong) {
//TODO do your stuff
}
});
And cancel this like:
timerSubscribe.unsubscribe();
Rx Timer http://reactivex.io/documentation/operators/timer.html
I'm surprised that there is no answer that would mention solution with RxJava2. It is really simple and provides an easy way to setup timer in Android.
First you need to setup Gradle dependency, if you didn't do so already:
implementation "io.reactivex.rxjava2:rxjava:2.x.y"
(replace x and y with current version number)
Since we have just a simple, NON-REPEATING TASK, we can use Completable object:
Completable.timer(2, TimeUnit.SECONDS, Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> {
// Timer finished, do something...
});
For REPEATING TASK, you can use Observable in a similar way:
Observable.interval(2, TimeUnit.SECONDS, Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(tick -> {
// called every 2 seconds, do something...
}, throwable -> {
// handle error
});
Schedulers.computation() ensures that our timer is running on background thread and .observeOn(AndroidSchedulers.mainThread()) means code we run after timer finishes will be done on main thread.
To avoid unwanted memory leaks, you should ensure to unsubscribe when Activity/Fragment is destroyed.
Because this question is still attracting a lot of users from google search(about Android timer) I would like to insert my two coins.
First of all, the Timer class will be deprecated in Java 9 (read the accepted answer).
The official suggested way is to use ScheduledThreadPoolExecutor which is more effective and features-rich that can additionally schedule commands to run after a given delay, or to execute periodically. Plus,it gives additional flexibility and capabilities of ThreadPoolExecutor.
Here is an example of using plain functionalities.
Create executor service:
final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);
Just schedule you runnable:
final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit);
You can now use future to cancel the task or check if it is done for example:
future.isDone();
Hope you will find this useful for creating a tasks in Android.
Complete example:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Future<?> sampleFutureTimer = scheduler.schedule(new Runnable(), 120, TimeUnit.SECONDS);
if (sampleFutureTimer.isDone()){
// Do something which will save world.
}
for whom wants to do this in kotlin:
val timer = fixedRateTimer(period = 1000L) {
val currentTime: Date = Calendar.getInstance().time
runOnUiThread {
tvFOO.text = currentTime.toString()
}
}
for stopping the timer you can use this:
timer.cancel()
this function has many other options, give it a try
import kotlin.concurrent.fixedRateTimer
val timer = fixedRateTimer("Tag", false, 1000, 2500) { /* Your code here */ }
Pretty simple with Kotlin
You want your UI updates to happen in the already-existent UI thread.
The best way is to use a Handler that uses postDelayed to run a Runnable after a delay (each run schedules the next); clear the callback with removeCallbacks.
You're already looking in the right place, so look at it again, perhaps clarify why that code sample isn't what you want. (See also the identical article at Updating the UI from a Timer).
He're is simplier solution, works fine in my app.
public class MyActivity extends Acitivity {
TextView myTextView;
boolean someCondition=true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
myTextView = (TextView) findViewById(R.id.refreshing_field);
//starting our task which update textview every 1000 ms
new RefreshTask().execute();
}
//class which updates our textview every second
class RefreshTask extends AsyncTask {
#Override
protected void onProgressUpdate(Object... values) {
super.onProgressUpdate(values);
String text = String.valueOf(System.currentTimeMillis());
myTextView.setText(text);
}
#Override
protected Object doInBackground(Object... params) {
while(someCondition) {
try {
//sleep for 1s in background...
Thread.sleep(1000);
//and update textview in ui thread
publishProgress();
} catch (InterruptedException e) {
e.printStackTrace();
};
return null;
}
}
}
You can also use an animator for it:
int secondsToRun = 999;
ValueAnimator timer = ValueAnimator.ofInt(secondsToRun);
timer.setDuration(secondsToRun * 1000).setInterpolator(new LinearInterpolator());
timer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
#Override
public void onAnimationUpdate(ValueAnimator animation)
{
int elapsedSeconds = (int) animation.getAnimatedValue();
int minutes = elapsedSeconds / 60;
int seconds = elapsedSeconds % 60;
textView.setText(String.format("%d:%02d", minutes, seconds));
}
});
timer.start();
For those who can't rely on Chronometer, I made a utility class out of one of the suggestions:
public class TimerTextHelper implements Runnable {
private final Handler handler = new Handler();
private final TextView textView;
private volatile long startTime;
private volatile long elapsedTime;
public TimerTextHelper(TextView textView) {
this.textView = textView;
}
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
textView.setText(String.format("%d:%02d", minutes, seconds));
if (elapsedTime == -1) {
handler.postDelayed(this, 500);
}
}
public void start() {
this.startTime = System.currentTimeMillis();
this.elapsedTime = -1;
handler.post(this);
}
public void stop() {
this.elapsedTime = System.currentTimeMillis() - startTime;
handler.removeCallbacks(this);
}
public long getElapsedTime() {
return elapsedTime;
}
}
to use..just do:
TimerTextHelper timerTextHelper = new TimerTextHelper(textView);
timerTextHelper.start();
.....
timerTextHelper.stop();
long elapsedTime = timerTextHelper.getElapsedTime();
enter code here
Thread th=new Thread(new Runnable() {
#Override
public void run() {
try { for(int i=0;i<5;i++) {
b1.setText(""+i);
Thread.sleep(5000);
runOnUiThread(new Runnable() {
#Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
pp();
}
}
});
}} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
th.start();
Here is the solution for this you need to add the following class in your code. And you can directly add a view to your XML file.
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
public class TimerTextView extends TextView {
private static final int DEFAULT_INTERVAL = 1000;
private Timer timer = new Timer();
private long endTime = 0;
private long interval = DEFAULT_INTERVAL;
private boolean isCanceled = false;
public TimerTextView(Context context) {
super(context);
}
public TimerTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TimerTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public TimerTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopTimer();
}
#Override protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (VISIBLE == visibility) {
startTimer();
} else {
stopTimer();
}
}
public void setInterval(long interval) {
if (interval >= 0) {
this.interval = interval;
stopTimer();
startTimer();
}
}
public void setEndTime(long endTime) {
if (endTime >= 0) {
this.endTime = endTime;
stopTimer();
startTimer();
}
}
private void startTimer() {
if (endTime == 0) {
return;
}
if (isCanceled) {
timer = new Timer();
isCanceled = false;
}
timer.scheduleAtFixedRate(new TimerTask() {
#Override public void run() {
if (null == getHandler()) {
return;
}
getHandler().post(new Runnable() {
#Override public void run() {
setText(getDurationBreakdown(endTime - System.currentTimeMillis()));
}
});
}
}, 0, interval);
}
private void stopTimer() {
timer.cancel();
isCanceled = true;
}
private String getDurationBreakdown(long diff) {
long millis = diff;
if (millis < 0) {
return "00:00:00";
}
long hours = TimeUnit.MILLISECONDS.toHours(millis);
millis -= TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
millis -= TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", hours, minutes, seconds);
//return "${getWithLeadZero(hours)}:${getWithLeadZero(minutes)}:${getWithLeadZero(seconds)}"
}
}
You need to create a thread to handle the update loop and use it to update the textarea. The tricky part though is that only the main thread can actually modify the ui so the update loop thread needs to signal the main thread to do the update. This is done using a Handler.
Check out this link: http://developer.android.com/guide/topics/ui/dialogs.html#
Click on the section titled "Example ProgressDialog with a second thread". It's an example of exactly what you need to do, except with a progress dialog instead of a textfield.
void method(boolean u,int max)
{
uu=u;
maxi=max;
if (uu==true)
{
CountDownTimer uy = new CountDownTimer(maxi, 1000)
{
public void onFinish()
{
text.setText("Finish");
}
#Override
public void onTick(long l) {
String currentTimeString=DateFormat.getTimeInstance().format(new Date());
text.setText(currentTimeString);
}
}.start();
}
else{text.setText("Stop ");
}
If anyone is interested, I started playing around with creating a standard object to run on an activities UI thread. Seems to work ok. Comments welcome. I'd love this to be available on the layout designer as a component to drag onto an Activity. Can't believe something like that doesn't already exist.
package com.example.util.timer;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
public class ActivityTimer {
private Activity m_Activity;
private boolean m_Enabled;
private Timer m_Timer;
private long m_Delay;
private long m_Period;
private ActivityTimerListener m_Listener;
private ActivityTimer _self;
private boolean m_FireOnce;
public ActivityTimer() {
m_Delay = 0;
m_Period = 100;
m_Listener = null;
m_FireOnce = false;
_self = this;
}
public boolean isEnabled() {
return m_Enabled;
}
public void setEnabled(boolean enabled) {
if (m_Enabled == enabled)
return;
// Disable any existing timer before we enable a new one
Disable();
if (enabled) {
Enable();
}
}
private void Enable() {
if (m_Enabled)
return;
m_Enabled = true;
m_Timer = new Timer();
if (m_FireOnce) {
m_Timer.schedule(new TimerTask() {
#Override
public void run() {
OnTick();
}
}, m_Delay);
} else {
m_Timer.schedule(new TimerTask() {
#Override
public void run() {
OnTick();
}
}, m_Delay, m_Period);
}
}
private void Disable() {
if (!m_Enabled)
return;
m_Enabled = false;
if (m_Timer == null)
return;
m_Timer.cancel();
m_Timer.purge();
m_Timer = null;
}
private void OnTick() {
if (m_Activity != null && m_Listener != null) {
m_Activity.runOnUiThread(new Runnable() {
#Override
public void run() {
m_Listener.OnTimerTick(m_Activity, _self);
}
});
}
if (m_FireOnce)
Disable();
}
public long getDelay() {
return m_Delay;
}
public void setDelay(long delay) {
m_Delay = delay;
}
public long getPeriod() {
return m_Period;
}
public void setPeriod(long period) {
if (m_Period == period)
return;
m_Period = period;
}
public Activity getActivity() {
return m_Activity;
}
public void setActivity(Activity activity) {
if (m_Activity == activity)
return;
m_Activity = activity;
}
public ActivityTimerListener getActionListener() {
return m_Listener;
}
public void setActionListener(ActivityTimerListener listener) {
m_Listener = listener;
}
public void start() {
if (m_Enabled)
return;
Enable();
}
public boolean isFireOnlyOnce() {
return m_FireOnce;
}
public void setFireOnlyOnce(boolean fireOnce) {
m_FireOnce = fireOnce;
}
}
In the activity, I have this onStart:
#Override
protected void onStart() {
super.onStart();
m_Timer = new ActivityTimer();
m_Timer.setFireOnlyOnce(true);
m_Timer.setActivity(this);
m_Timer.setActionListener(this);
m_Timer.setDelay(3000);
m_Timer.start();
}
Here is a simple reliable way...
Put the following code in your Activity, and the tick() method will be called every second in the UI thread while your activity is in the "resumed" state. Of course, you can change the tick() method to do what you want, or to be called more or less frequently.
#Override
public void onPause() {
_handler = null;
super.onPause();
}
private Handler _handler;
#Override
public void onResume() {
super.onResume();
_handler = new Handler();
Runnable r = new Runnable() {
public void run() {
if (_handler == _h0) {
tick();
_handler.postDelayed(this, 1000);
}
}
private final Handler _h0 = _handler;
};
r.run();
}
private void tick() {
System.out.println("Tick " + System.currentTimeMillis());
}
For those interested, the "_h0=_handler" code is necessary to avoid two timers running simultaneously if your activity is paused and resumed within the tick period.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.app.Activity;
public class MainActivity extends Activity {
CheckBox optSingleShot;
Button btnStart, btnCancel;
TextView textCounter;
Timer timer;
MyTimerTask myTimerTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
optSingleShot = (CheckBox)findViewById(R.id.singleshot);
btnStart = (Button)findViewById(R.id.start);
btnCancel = (Button)findViewById(R.id.cancel);
textCounter = (TextView)findViewById(R.id.counter);
btnStart.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
if(timer != null){
timer.cancel();
}
//re-schedule timer here
//otherwise, IllegalStateException of
//"TimerTask is scheduled already"
//will be thrown
timer = new Timer();
myTimerTask = new MyTimerTask();
if(optSingleShot.isChecked()){
//singleshot delay 1000 ms
timer.schedule(myTimerTask, 1000);
}else{
//delay 1000ms, repeat in 5000ms
timer.schedule(myTimerTask, 1000, 5000);
}
}});
btnCancel.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
if (timer!=null){
timer.cancel();
timer = null;
}
}
});
}
class MyTimerTask extends TimerTask {
#Override
public void run() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat =
new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
final String strDate = simpleDateFormat.format(calendar.getTime());
runOnUiThread(new Runnable(){
#Override
public void run() {
textCounter.setText(strDate);
}});
}
}
}
.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<CheckBox
android:id="#+id/singleshot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Single Shot"/>
If you have delta time already.
public class Timer {
private float lastFrameChanged;
private float frameDuration;
private Runnable r;
public Timer(float frameDuration, Runnable r) {
this.frameDuration = frameDuration;
this.lastFrameChanged = 0;
this.r = r;
}
public void update(float dt) {
lastFrameChanged += dt;
if (lastFrameChanged > frameDuration) {
lastFrameChanged = 0;
r.run();
}
}
}
I Abstract Timer away and made it a separate class:
Timer.java
import android.os.Handler;
public class Timer {
IAction action;
Handler timerHandler = new Handler();
int delayMS = 1000;
public Timer(IAction action, int delayMS) {
this.action = action;
this.delayMS = delayMS;
}
public Timer(IAction action) {
this(action, 1000);
}
public Timer() {
this(null);
}
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
if (action != null)
action.Task();
timerHandler.postDelayed(this, delayMS);
}
};
public void start() {
timerHandler.postDelayed(timerRunnable, 0);
}
public void stop() {
timerHandler.removeCallbacks(timerRunnable);
}
}
And Extract main action from Timer class out as
IAction.java
public interface IAction {
void Task();
}
And I used it just like this:
MainActivity.java
public class MainActivity extends Activity implements IAction{
...
Timer timerClass;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
timerClass = new Timer(this,1000);
timerClass.start();
...
}
...
int i = 1;
#Override
public void Task() {
runOnUiThread(new Runnable() {
#Override
public void run() {
timer.setText(i + "");
i++;
}
});
}
...
}
I Hope This Helps 😊👌
I use this way:
String[] array={
"man","for","think"
}; int j;
then below the onCreate
TextView t = findViewById(R.id.textView);
new CountDownTimer(5000,1000) {
#Override
public void onTick(long millisUntilFinished) {}
#Override
public void onFinish() {
t.setText("I "+array[j] +" You");
j++;
if(j== array.length-1) j=0;
start();
}
}.start();
it's easy way to solve this problem.
Related
Loop a Countdown timer X number of times,
I'm trying to loop my countdown timer for a specific number of times, but I'm not sure where I should add my for loop... Currently trying to do an interval timer function (I know there's a way to do it via Handler, but I'm still a beginner and got kind of confused on how I shoul use the handler) I've tried adding it at '.start' and the StartTimer function but the countdown time still stays at 0. Would be great if any assistance is given as I'm still a beginner.. Thanks! package com.example.bushykai.myapplication; import android.os.CountDownTimer; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class Timer extends AppCompatActivity { private static final long START_TIME_IN_MILLIS=10000; private int sets = 3; private TextView textViewCountdown; private Button buttonStartPause; private Button buttonReset; private CountDownTimer countDownTimer; private boolean timerRunning; private long timeLeftInMillis = START_TIME_IN_MILLIS; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_timer); textViewCountdown = findViewById(R.id.countdownTimer); buttonStartPause = findViewById(R.id.startPause); buttonReset= findViewById(R.id.reset); buttonStartPause.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { if (timerRunning) { pauseTimer(); } else { startTimer(); } } }); buttonReset.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { resetTimer(); } }); updateCountDownText(); } private void pauseTimer() { countDownTimer.cancel(); timerRunning = false; buttonStartPause.setText("Start"); buttonReset.setVisibility(View.VISIBLE); } private void startTimer() { countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) { #Override public void onTick(long millisUntilFinished) { timeLeftInMillis = millisUntilFinished; updateCountDownText(); } #Override public void onFinish() { timerRunning = false; buttonStartPause.setText("Start"); buttonStartPause.setVisibility(View.INVISIBLE); buttonReset.setVisibility(View.VISIBLE); } }.start(); timerRunning = true; buttonStartPause.setText("Pause"); buttonReset.setVisibility((View.INVISIBLE)); } private void resetTimer() { timeLeftInMillis = START_TIME_IN_MILLIS; updateCountDownText(); buttonReset.setVisibility(View.INVISIBLE); buttonStartPause.setVisibility(View.VISIBLE); } private void updateCountDownText() { int minutes = (int) (timeLeftInMillis / 1000 ) / 60; int seconds = (int) (timeLeftInMillis / 1000 ) % 60; String timeLeftFormatted = String.format("%02d:%02d", minutes, seconds); textViewCountdown.setText(timeLeftFormatted); } }
You have to add a Runnable Handler to your class try code below and modify with your Countdown Timer public Handler timerHandler = new Handler(); public Runnable timerRunnable = new Runnable() { #Override public void run() { //show alert or DO Whatever } }; public void timerStart() { timerStop(); timerHandler.postDelayed(timerRunnable, Constants.TIMER_TIME_OUT); } public void timerStop() { timerHandler.removeCallbacks(timerRunnable); }
CountDownTimer Is Not Cancelling --- Continues to Run After Cancel()
I've implemented a CountDownTimer in my code as follows: At the top of the class, I create CountDownTimer myTimer; Then when a user presses button Start, the following method is called: private void countme() { final int tick = 500; final int countTime = 10000; myTimer = new CountDownTimer(countTime, tick) { #Override public void onTick(final long millisUntilFinished) { } #Override public void onFinish() { myPicture.setVisibility(View.GONE); } }; myTimer.start(); } I have button Stop all myTimer.cancel(). As you can see, if the timer is not cancelled, myPicture will disappear. Even if I click the stop button so that myTimer.cancel() is called (I checked this with log statements), the counter still continues to count down and to make the picture disappear when it's done. Why isn't it stopping? How do I get it to actually cancel? To clarify, I do know how to implement Runnable timers, but they are not as accurate for my needs as CountDownTimers are, which is why I'm not using them in this case.
After a lot of tries, trick is to declare the timer in onCreate but start and cancel it in some other method. The onFinish() will not call after cancelling the timer. myTimer = new CountDownTimer(COUNT_DOWN_TIME, TICK) { #Override public void onTick(final long millisUntilFinished) { ((TextView) findViewById(R.id.textView3)).setText("" + millisUntilFinished); } #Override public void onFinish() { findViewById(R.id.timer_imageBiew).setVisibility(View.GONE); } }; private fun startTimer() { myTimer .start() } private fun stopTimer() { myTimer .cancel() }
Here in your method countme() you are initializing myTimer, so outside this method myTimer has no value. Use this Declare at the top CountDownTimer myTimer; final int tick = 500; final int countTime = 10000; In the onCreate method of Activity or Fragment myTimer = new CountDownTimer(countTime, tick) { #Override public void onTick(final long millisUntilFinished) { } #Override public void onFinish() { myPicture.setVisibility(View.GONE); } }; Now use myTimer.start() to start and myTimer.cancel() to stop it. Hope you understood.
Your post is very odd. I just tried doing a sample activity: public class MainActivity extends AppCompatActivity { CountDownTimer myTimer; Button btnStart; Button btnCancel; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.sample2); btnStart = (Button) findViewById(R.id.start); btnStart.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { countme(); Toast.makeText(MainActivity.this, "Count Started!", Toast.LENGTH_SHORT).show(); } }); btnCancel = (Button) findViewById(R.id.cancel_timer); btnCancel.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { myTimer.cancel(); Toast.makeText(MainActivity.this, "Clicked Stop Timer!", Toast.LENGTH_SHORT).show(); } }); } private void countme() { final int tick = 500; final int countTime = 10000; myTimer = new CountDownTimer(countTime, tick) { #Override public void onTick(final long millisUntilFinished) { Log.d(MainActivity.class.getSimpleName(), "onTick()"); } #Override public void onFinish() { // myPicture.setVisibility(View.GONE); Toast.makeText(MainActivity.this, "In onFinish()", Toast.LENGTH_SHORT).show(); } }; myTimer.start(); } } It works perfectly fine. It stops the timer. But I went and looked around and found this answer where it mentions that CountDownTimer doesn't seem to work, so he suggested to use a Timer instead. Do check it out. Cheers!
This is working example , I have implemented both handler and timer you can pick one . import android.app.Activity; import android.os.Bundle; import android.os.CountDownTimer; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; public class MainActivity extends Activity { private CountDownTimer myTimer; final int TICK = 500; final int COUNT_DOWN_TIME = 2000; // Option 2 using handler private Handler myhandler = new Handler(); private Runnable runnable; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Option 1 using timer myTimer = new CountDownTimer(COUNT_DOWN_TIME, TICK) { #Override public void onTick(final long millisUntilFinished) { ((TextView) findViewById(R.id.textView3)).setText("" + millisUntilFinished); } #Override public void onFinish() { findViewById(R.id.timer_imageBiew).setVisibility(View.GONE); } }; // Option 2 using handler runnable = new Runnable() { #Override public void run() { findViewById(R.id.handlerImageView).setVisibility(View.GONE); } }; findViewById(R.id.start_timer).setOnClickListener( new OnClickListener() { #Override public void onClick(View v) { // Option 1 using timer myTimer.start(); // Option 2 using handler myhandler.postDelayed(runnable, COUNT_DOWN_TIME); } }); findViewById(R.id.stop_timer).setOnClickListener(new OnClickListener() { #Override public void onClick(View v) { // Option 1 stop timer myTimer.cancel(); // Option 2 stop handler myhandler.removeCallbacks(runnable); } }); } }
Countdown timer with pause and resume
I want to do countdown timer with pause and restart.Now i am displaying countdown timer By implenting ontick() and onfinish().please help me out.HEre is th code for countdown timer final CountDownTimer Counter1 = new CountDownTimer(timervalue1 , 1000) { public void onTick(long millisUntilFinished) { System.out.println("onTick method!"(String.valueOf(millisUntilFinished/1000)));long s1=millisUntilFinished; } public void onFinish() { System.out.println("Finished!"); } }
in onTick method..save the milliseconds left long s1=millisUntilFinished; when you want to pause the timer use.. Counter.cancel(); when you want to resume create a new countdowntimer with left milliseconds.. timervalue=s1 counter= new Counter1(); counter.start(); See this link
I would add something to the onTick handler to save the progress of the timer in your class (number of milliseconds left). In the onPause() method for the activity call cancel() on the timer. In the onResume() method for the activity create a new timer with the saved number of milliseconds left. Refer the below links LINK LINK
My first answer on stackOverFlow, hope it should help :) ... This is how I solved the problem, control timer from Fragment, Bottomsheet, Service, Dialog as per your requirement, keep a static boolean variable to control. declare in your Activity: long presetTime, runningTime; Handler mHandler =new Handler(); Runnable countDownRunnable; Toast toastObj; public static boolean shouldTimerRun = true; TextView counterTv; In onCreate: presetTime =60000L; runningTime= presetTime; //setting up Timer countDownRunnable=new Runnable() { #Override public void run() { if (shouldTimerRun) //if false, it runs but skips counting { counterTv.setText(simplifyTimeInMillis(runningTime)); if (runningTime==0) { deployToast("Task Completed"); //show toast on task completion } runningTime -= 1000; presetTime = runningTime; //to resume the timer from last position } mHandler.postDelayed(countDownRunnable,1000); //simulating on-tick } }; mHandler.post(countDownRunnable); // Start our CountdownTimer Now, whenever you want to pause the timer change the value of shouldTimerRun false and to resume make it true. #Override public void onResume() { super.onResume(); shouldTimerRun=true; } #Override public void onPause() { super.onPause(); shouldTimerRun=false; deployToast("Timer is paused !!"); } Helping methods: (can be skipped) public static String simplifyTimeInMillis(long time) { String result=""; long difference = time; long secondsInMilli = 1000; long minutesInMilli = secondsInMilli * 60; long hoursInMilli = minutesInMilli * 60; if (difference<1000){ return "0"; } if (difference>=3600000) { result = result + String.valueOf(difference / hoursInMilli) + "hr "; difference = difference % hoursInMilli; } if (difference>=60000) { result = result + String.valueOf(difference / minutesInMilli) + "m "; difference = difference % minutesInMilli; } if (difference>=1000){ result = result + String.valueOf(difference / secondsInMilli) + "s"; } return result; } public void deployToast(String msg){ if (toastObj!=null) toastObj.cancel(); toastObj = Toast.makeText(mContext,msg,Toast.LENGTH_SHORT); toastObj.show(); }
I'm using two private vars in this case: private long startPauseTime; private long pauseTime = 0L; public void pause() { startPauseTime = System.currentTimeMillis(); } public void resumen(){ pauseTime += System.currentTimeMillis() - startPauseTime; }
I am afraid that it is not possible to pause or stop CountDownTimer and pausing or stopping in onTick has no effect whatsoever user TimerTask instead. Set up the TimerTask class UpdateTimeTask extends TimerTask { public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; timeLabel.setText(String.format("%d:%02d", minutes, seconds)); } } if(startTime == 0L) { startTime = evt.getWhen(); timer = new Timer(); timer.schedule(new UpdateTimeTask(), 100, 200); } You can add event listener's like this.. private Handler mHandler = new Handler(); ... OnClickListener mStartListener = new OnClickListener() { public void onClick(View v) { if (mStartTime == 0L) { mStartTime = System.currentTimeMillis(); mHandler.removeCallbacks(mUpdateTimeTask); mHandler.postDelayed(mUpdateTimeTask, 100); } } }; OnClickListener mStopListener = new OnClickListener() { public void onClick(View v) { mHandler.removeCallbacks(mUpdateTimeTask); } }; For more refer to Android Documentation.
//This timer will show min:sec format and can be paused and resumed public class YourClass extends Activity{ TextView timer; CountDownTimer ct; long c = 150000; // 2min:30sec Timer protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.YourXmlLayout); timer = (TextView)findViewById(R.id.Yourtimer) startTimer(); // it will start the timer } public void startTimer(){ ct = new CountDownTimer(c,1000) { #Override public void onTick(long millisUntilFinished) { // Code to show the timer in min:sec form // Here timer is a TextView so timer.setText(""+String.format("%02d:%02d",millisUntilFinished/60000,(millisUntilFinished/1000)%60)); c = millisUntilFinished; // it will store millisLeft } #Override public void onFinish() { //your code here } }; ct.start(); } /*=========================================================== *after creating this you can pause this by typing ct.cancel() *and resume by typing startTimer()*/
public class MainActivity extends AppCompatActivity { TextView textView; CountDownTimer ctimer; boolean runCountDown; private long leftTime; private static final long MILL_IN_FUTURE = 6000; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.text_view); textView.setText("Click to start"); textView.setOnClickListener(this::clickStartAndPauseAndResume); leftTime = MILL_IN_FUTURE; } public void clickStartAndPauseAndResume(View view) { if (!runCountDown) { long time = (leftTime == 0 || leftTime == MILL_IN_FUTURE) ? MILL_IN_FUTURE : leftTime; ctimer = new CountDownTimer(time, 1) { #Override public void onTick(long l) { leftTime = l; textView.setText(l + "ms"); } #Override public void onFinish() { textView.setText("Done"); leftTime = 0; runCountDown = false; textView.postDelayed(new Runnable() { #Override public void run() { textView.setText("Click to start"); } }, 1000); } }.start(); runCountDown = true; } else { ctimer.cancel(); textView.setText(textView.getText() + "\n Click to resume"); runCountDown = false; } } }
A nice and simple way to create a Pause/Resume for your CountDownTimer is to create a separate method for your timer start, pause and resume as follows: public void timerStart(long timeLengthMilli) { timer = new CountDownTimer(timeLengthMilli, 1000) { #Override public void onTick(long milliTillFinish) { milliLeft=milliTillFinish; min = (milliTillFinish/(1000*60)); sec = ((milliTillFinish/1000)-min*60); clock.setText(Long.toString(min)+":"+Long.toString(sec)); Log.i("Tick", "Tock"); } The timerStart has a long parameter as it will be reused by the resume() method below. Remember to store your milliTillFinished (above as milliLeft) so that you may send it through in your resume() method. Pause and resume methods below respectively: public void timerPause() { timer.cancel(); } private void timerResume() { Log.i("min", Long.toString(min)); Log.i("Sec", Long.toString(sec)); timerStart(milliLeft); } Here is the code for the button FYI: startPause.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View view) { if(startPause.getText().equals("Start")){ Log.i("Started", startPause.getText().toString()); startPause.setText("Pause"); timerStart(15*1000); } else if (startPause.getText().equals("Pause")){ Log.i("Paused", startPause.getText().toString()); startPause.setText("Resume"); timerPause(); } else if (startPause.getText().equals("Resume")){ startPause.setText("Pause"); timerResume(); }
How to create an infinite loop
Ok,I need to create an infinite loop on a countdown. My code is: public void countdown() { if (x != null) { x.cancel(); } x = new CountDownTimer(20000, 1000) { public void onTick(long millisUntilFinished) { } public void onFinish() { showNotification(); } }; x.start(); } x is just a static countdowntimer variable. The problem is that I tried many methods to make the above code work,I mean when the countdown ends,and it displays that notification,it should start again and so on....but I can't find a way to do it.
Hope this will help you. public void countdown(){ if (x != null) { x.cancel(); } x = new CountDownTimer(20000, 1000) { public void onTick(long millisUntilFinished) { } public void onFinish() { showNotification(); x.start(); } }; }
For the record CountDownTimer(long millisInFuture, long countDownInterval) // A not so infinite but close to infinte interval for each second CountDownTimer cdt=new CountDownTimer(Long.MAX_VALUE, 1000) { .... } Where Long.MAX_VALUE = 9223372036854775807 miliseconds or around 292 million of years (seconds more or less) Its not infinite but its incredibly long.
is to restart your timer when his has finished :) like this : x = new CountDownTimer(20000, 1000) { public void onTick(long millisUntilFinished) { } public void onFinish() { showNotification(); start();// here, when your CountDownTimer has finished , we start it again :) } }; x.start();
Simple way to create an infinite loop: Every one secod call method new CountDownTimer(1000, 1000) { public void onTick(long l) {} public void onFinish() { //Code hear start(); } }.start();
Why not just use a regular Timer? It will repeat on a specified interval until you call cancel(), something like: public void countdown() { if (x != null) { x.cancel(); } x = new Timer("timerName"); x.schedule(_timerTask, 0, 20000); } private static final TimerTask _timerTask = new TimerTask() { #Override public void run() { showNotification(); } };
You can just use a while loop: while (true) { // do stuff } When it has done "the stuff" it wil start again, infinite!
to keep your timer working just put <countdowntime>.start(); in the onfinish block
Well, I have implemented an indefinite timer that takes multiple listeners and calls them simultaneously on a specific interval. import android.os.CountDownTimer; import java.util.Arrays; public class InfiniteCounter extends CountDownTimer { private static final int MAX_LISTENERS = 100; private static InfiniteCounter timer; private static InfiniteCounterListener[] listenerList = new InfiniteCounterListener[MAX_LISTENERS]; private InfiniteCounter(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } //Milliseconds Intervals in which the counter should call its listeners public static InfiniteCounter initInstance(int intervalMillis) { removeAllListeners(); if (timer == null) { timer = new InfiniteCounter(60 * 60 * 1000, intervalMillis); timer.start(); } return timer; } public static void attachListener(InfiniteCounterListener listener) { for (int i = 0; i < MAX_LISTENERS; i++) { if (listenerList[i] == null) { listenerList[i] = listener; break; } } } public static void removeListener(InfiniteCounterListener listener) { for (int i = 0; i < MAX_LISTENERS; i++) { if (listenerList[i] == listener) { listenerList[i] = null; break; } } } private static void removeAllListeners() { Arrays.fill(listenerList, null); } public static void stopTimer() { removeAllListeners(); if (timer != null) timer.cancel(); timer = null; } #Override public void onTick(long l) { for (int i = 0; i < MAX_LISTENERS; i++) { if (listenerList[i] != null) listenerList[i].onTick(); } } #Override public void onFinish() { timer.start(); } public interface InfiniteCounterListener { void onTick(); } } Just Attach listeners to this class and with single timer, it can call multiple listeners -- which makes is very performance optimised.
How to set timer in android?
Can someone give a simple example of updating a textfield every second or so? I want to make a flying ball and need to calculate/update the ball coordinates every second, that's why I need some sort of a timer. I don't get anything from here.
ok since this isn't cleared up yet there are 3 simple ways to handle this. Below is an example showing all 3 and at the bottom is an example showing just the method I believe is preferable. Also remember to clean up your tasks in onPause, saving state if necessary. import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Handler.Callback; import android.view.View; import android.widget.Button; import android.widget.TextView; public class main extends Activity { TextView text, text2, text3; long starttime = 0; //this posts a message to the main thread from our timertask //and updates the textfield final Handler h = new Handler(new Callback() { #Override public boolean handleMessage(Message msg) { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text.setText(String.format("%d:%02d", minutes, seconds)); return false; } }); //runs without timer be reposting self Handler h2 = new Handler(); Runnable run = new Runnable() { #Override public void run() { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text3.setText(String.format("%d:%02d", minutes, seconds)); h2.postDelayed(this, 500); } }; //tells handler to send a message class firstTask extends TimerTask { #Override public void run() { h.sendEmptyMessage(0); } }; //tells activity to run on ui thread class secondTask extends TimerTask { #Override public void run() { main.this.runOnUiThread(new Runnable() { #Override public void run() { long millis = System.currentTimeMillis() - starttime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; text2.setText(String.format("%d:%02d", minutes, seconds)); } }); } }; Timer timer = new Timer(); #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); text = (TextView)findViewById(R.id.text); text2 = (TextView)findViewById(R.id.text2); text3 = (TextView)findViewById(R.id.text3); Button b = (Button)findViewById(R.id.button); b.setText("start"); b.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { Button b = (Button)v; if(b.getText().equals("stop")){ timer.cancel(); timer.purge(); h2.removeCallbacks(run); b.setText("start"); }else{ starttime = System.currentTimeMillis(); timer = new Timer(); timer.schedule(new firstTask(), 0,500); timer.schedule(new secondTask(), 0,500); h2.postDelayed(run, 0); b.setText("stop"); } } }); } #Override public void onPause() { super.onPause(); timer.cancel(); timer.purge(); h2.removeCallbacks(run); Button b = (Button)findViewById(R.id.button); b.setText("start"); } } the main thing to remember is that the UI can only be modified from the main ui thread so use a handler or activity.runOnUIThread(Runnable r); Here is what I consider to be the preferred method. import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.Button; import android.widget.TextView; public class TestActivity extends Activity { TextView timerTextView; long startTime = 0; //runs without a timer by reposting this handler at the end of the runnable Handler timerHandler = new Handler(); Runnable timerRunnable = new Runnable() { #Override public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; timerTextView.setText(String.format("%d:%02d", minutes, seconds)); timerHandler.postDelayed(this, 500); } }; #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_activity); timerTextView = (TextView) findViewById(R.id.timerTextView); Button b = (Button) findViewById(R.id.button); b.setText("start"); b.setOnClickListener(new View.OnClickListener() { #Override public void onClick(View v) { Button b = (Button) v; if (b.getText().equals("stop")) { timerHandler.removeCallbacks(timerRunnable); b.setText("start"); } else { startTime = System.currentTimeMillis(); timerHandler.postDelayed(timerRunnable, 0); b.setText("stop"); } } }); } #Override public void onPause() { super.onPause(); timerHandler.removeCallbacks(timerRunnable); Button b = (Button)findViewById(R.id.button); b.setText("start"); } }
It is simple! You create new timer. Timer timer = new Timer(); Then you extend the timer task class UpdateBallTask extends TimerTask { Ball myBall; public void run() { //calculate the new position of myBall } } And then add the new task to the Timer with some update interval final int FPS = 40; TimerTask updateBall = new UpdateBallTask(); timer.scheduleAtFixedRate(updateBall, 0, 1000/FPS); Disclaimer: This is not the ideal solution. This is solution using the Timer class (as asked by OP). In Android SDK, it is recommended to use the Handler class (there is example in the accepted answer).
If you also need to run your code on UI thread (and not on timer thread), take a look on the blog: http://steve.odyfamily.com/?p=12 public class myActivity extends Activity { private Timer myTimer; /** Called when the activity is first created. */ #Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); myTimer = new Timer(); myTimer.schedule(new TimerTask() { #Override public void run() { TimerMethod(); } }, 0, 1000); } private void TimerMethod() { //This method is called directly by the timer //and runs in the same thread as the timer. //We call the method that will work with the UI //through the runOnUiThread method. this.runOnUiThread(Timer_Tick); } private Runnable Timer_Tick = new Runnable() { public void run() { //This method runs in the same thread as the UI. //Do something to the UI thread here } }; }
If one just want to schedule a countdown until a time in the future with regular notifications on intervals along the way, you can use the CountDownTimer class that is available since API level 1. new CountDownTimer(30000, 1000) { public void onTick(long millisUntilFinished) { editText.setText("Seconds remaining: " + millisUntilFinished / 1000); } public void onFinish() { editText.setText("Done"); } }.start();
This is some simple code for a timer: Timer timer = new Timer(); TimerTask t = new TimerTask() { #Override public void run() { System.out.println("1"); } }; timer.scheduleAtFixedRate(t,1000,1000);
I think you can do it in Rx way like: timerSubscribe = Observable.interval(1, TimeUnit.SECONDS) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Long>() { #Override public void call(Long aLong) { //TODO do your stuff } }); And cancel this like: timerSubscribe.unsubscribe(); Rx Timer http://reactivex.io/documentation/operators/timer.html
I'm surprised that there is no answer that would mention solution with RxJava2. It is really simple and provides an easy way to setup timer in Android. First you need to setup Gradle dependency, if you didn't do so already: implementation "io.reactivex.rxjava2:rxjava:2.x.y" (replace x and y with current version number) Since we have just a simple, NON-REPEATING TASK, we can use Completable object: Completable.timer(2, TimeUnit.SECONDS, Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(() -> { // Timer finished, do something... }); For REPEATING TASK, you can use Observable in a similar way: Observable.interval(2, TimeUnit.SECONDS, Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(tick -> { // called every 2 seconds, do something... }, throwable -> { // handle error }); Schedulers.computation() ensures that our timer is running on background thread and .observeOn(AndroidSchedulers.mainThread()) means code we run after timer finishes will be done on main thread. To avoid unwanted memory leaks, you should ensure to unsubscribe when Activity/Fragment is destroyed.
Because this question is still attracting a lot of users from google search(about Android timer) I would like to insert my two coins. First of all, the Timer class will be deprecated in Java 9 (read the accepted answer). The official suggested way is to use ScheduledThreadPoolExecutor which is more effective and features-rich that can additionally schedule commands to run after a given delay, or to execute periodically. Plus,it gives additional flexibility and capabilities of ThreadPoolExecutor. Here is an example of using plain functionalities. Create executor service: final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1); Just schedule you runnable: final Future<?> future = SCHEDULER.schedule(Runnable task, long delay,TimeUnit unit); You can now use future to cancel the task or check if it is done for example: future.isDone(); Hope you will find this useful for creating a tasks in Android. Complete example: ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); Future<?> sampleFutureTimer = scheduler.schedule(new Runnable(), 120, TimeUnit.SECONDS); if (sampleFutureTimer.isDone()){ // Do something which will save world. }
for whom wants to do this in kotlin: val timer = fixedRateTimer(period = 1000L) { val currentTime: Date = Calendar.getInstance().time runOnUiThread { tvFOO.text = currentTime.toString() } } for stopping the timer you can use this: timer.cancel() this function has many other options, give it a try
import kotlin.concurrent.fixedRateTimer val timer = fixedRateTimer("Tag", false, 1000, 2500) { /* Your code here */ } Pretty simple with Kotlin
You want your UI updates to happen in the already-existent UI thread. The best way is to use a Handler that uses postDelayed to run a Runnable after a delay (each run schedules the next); clear the callback with removeCallbacks. You're already looking in the right place, so look at it again, perhaps clarify why that code sample isn't what you want. (See also the identical article at Updating the UI from a Timer).
He're is simplier solution, works fine in my app. public class MyActivity extends Acitivity { TextView myTextView; boolean someCondition=true; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_activity); myTextView = (TextView) findViewById(R.id.refreshing_field); //starting our task which update textview every 1000 ms new RefreshTask().execute(); } //class which updates our textview every second class RefreshTask extends AsyncTask { #Override protected void onProgressUpdate(Object... values) { super.onProgressUpdate(values); String text = String.valueOf(System.currentTimeMillis()); myTextView.setText(text); } #Override protected Object doInBackground(Object... params) { while(someCondition) { try { //sleep for 1s in background... Thread.sleep(1000); //and update textview in ui thread publishProgress(); } catch (InterruptedException e) { e.printStackTrace(); }; return null; } } }
You can also use an animator for it: int secondsToRun = 999; ValueAnimator timer = ValueAnimator.ofInt(secondsToRun); timer.setDuration(secondsToRun * 1000).setInterpolator(new LinearInterpolator()); timer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { #Override public void onAnimationUpdate(ValueAnimator animation) { int elapsedSeconds = (int) animation.getAnimatedValue(); int minutes = elapsedSeconds / 60; int seconds = elapsedSeconds % 60; textView.setText(String.format("%d:%02d", minutes, seconds)); } }); timer.start();
For those who can't rely on Chronometer, I made a utility class out of one of the suggestions: public class TimerTextHelper implements Runnable { private final Handler handler = new Handler(); private final TextView textView; private volatile long startTime; private volatile long elapsedTime; public TimerTextHelper(TextView textView) { this.textView = textView; } #Override public void run() { long millis = System.currentTimeMillis() - startTime; int seconds = (int) (millis / 1000); int minutes = seconds / 60; seconds = seconds % 60; textView.setText(String.format("%d:%02d", minutes, seconds)); if (elapsedTime == -1) { handler.postDelayed(this, 500); } } public void start() { this.startTime = System.currentTimeMillis(); this.elapsedTime = -1; handler.post(this); } public void stop() { this.elapsedTime = System.currentTimeMillis() - startTime; handler.removeCallbacks(this); } public long getElapsedTime() { return elapsedTime; } } to use..just do: TimerTextHelper timerTextHelper = new TimerTextHelper(textView); timerTextHelper.start(); ..... timerTextHelper.stop(); long elapsedTime = timerTextHelper.getElapsedTime();
enter code here Thread th=new Thread(new Runnable() { #Override public void run() { try { for(int i=0;i<5;i++) { b1.setText(""+i); Thread.sleep(5000); runOnUiThread(new Runnable() { #Override public void run() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { pp(); } } }); }} catch (InterruptedException e) { e.printStackTrace(); } } }); th.start();
Here is the solution for this you need to add the following class in your code. And you can directly add a view to your XML file. import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.util.AttributeSet; import android.view.View; import android.widget.TextView; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; public class TimerTextView extends TextView { private static final int DEFAULT_INTERVAL = 1000; private Timer timer = new Timer(); private long endTime = 0; private long interval = DEFAULT_INTERVAL; private boolean isCanceled = false; public TimerTextView(Context context) { super(context); } public TimerTextView(Context context, AttributeSet attrs) { super(context, attrs); } public TimerTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } #TargetApi(Build.VERSION_CODES.LOLLIPOP) public TimerTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } #Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); stopTimer(); } #Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); if (VISIBLE == visibility) { startTimer(); } else { stopTimer(); } } public void setInterval(long interval) { if (interval >= 0) { this.interval = interval; stopTimer(); startTimer(); } } public void setEndTime(long endTime) { if (endTime >= 0) { this.endTime = endTime; stopTimer(); startTimer(); } } private void startTimer() { if (endTime == 0) { return; } if (isCanceled) { timer = new Timer(); isCanceled = false; } timer.scheduleAtFixedRate(new TimerTask() { #Override public void run() { if (null == getHandler()) { return; } getHandler().post(new Runnable() { #Override public void run() { setText(getDurationBreakdown(endTime - System.currentTimeMillis())); } }); } }, 0, interval); } private void stopTimer() { timer.cancel(); isCanceled = true; } private String getDurationBreakdown(long diff) { long millis = diff; if (millis < 0) { return "00:00:00"; } long hours = TimeUnit.MILLISECONDS.toHours(millis); millis -= TimeUnit.HOURS.toMillis(hours); long minutes = TimeUnit.MILLISECONDS.toMinutes(millis); millis -= TimeUnit.MINUTES.toMillis(minutes); long seconds = TimeUnit.MILLISECONDS.toSeconds(millis); return String.format(Locale.ENGLISH, "%02d:%02d:%02d", hours, minutes, seconds); //return "${getWithLeadZero(hours)}:${getWithLeadZero(minutes)}:${getWithLeadZero(seconds)}" } }
You need to create a thread to handle the update loop and use it to update the textarea. The tricky part though is that only the main thread can actually modify the ui so the update loop thread needs to signal the main thread to do the update. This is done using a Handler. Check out this link: http://developer.android.com/guide/topics/ui/dialogs.html# Click on the section titled "Example ProgressDialog with a second thread". It's an example of exactly what you need to do, except with a progress dialog instead of a textfield.
void method(boolean u,int max) { uu=u; maxi=max; if (uu==true) { CountDownTimer uy = new CountDownTimer(maxi, 1000) { public void onFinish() { text.setText("Finish"); } #Override public void onTick(long l) { String currentTimeString=DateFormat.getTimeInstance().format(new Date()); text.setText(currentTimeString); } }.start(); } else{text.setText("Stop "); }
If anyone is interested, I started playing around with creating a standard object to run on an activities UI thread. Seems to work ok. Comments welcome. I'd love this to be available on the layout designer as a component to drag onto an Activity. Can't believe something like that doesn't already exist. package com.example.util.timer; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; public class ActivityTimer { private Activity m_Activity; private boolean m_Enabled; private Timer m_Timer; private long m_Delay; private long m_Period; private ActivityTimerListener m_Listener; private ActivityTimer _self; private boolean m_FireOnce; public ActivityTimer() { m_Delay = 0; m_Period = 100; m_Listener = null; m_FireOnce = false; _self = this; } public boolean isEnabled() { return m_Enabled; } public void setEnabled(boolean enabled) { if (m_Enabled == enabled) return; // Disable any existing timer before we enable a new one Disable(); if (enabled) { Enable(); } } private void Enable() { if (m_Enabled) return; m_Enabled = true; m_Timer = new Timer(); if (m_FireOnce) { m_Timer.schedule(new TimerTask() { #Override public void run() { OnTick(); } }, m_Delay); } else { m_Timer.schedule(new TimerTask() { #Override public void run() { OnTick(); } }, m_Delay, m_Period); } } private void Disable() { if (!m_Enabled) return; m_Enabled = false; if (m_Timer == null) return; m_Timer.cancel(); m_Timer.purge(); m_Timer = null; } private void OnTick() { if (m_Activity != null && m_Listener != null) { m_Activity.runOnUiThread(new Runnable() { #Override public void run() { m_Listener.OnTimerTick(m_Activity, _self); } }); } if (m_FireOnce) Disable(); } public long getDelay() { return m_Delay; } public void setDelay(long delay) { m_Delay = delay; } public long getPeriod() { return m_Period; } public void setPeriod(long period) { if (m_Period == period) return; m_Period = period; } public Activity getActivity() { return m_Activity; } public void setActivity(Activity activity) { if (m_Activity == activity) return; m_Activity = activity; } public ActivityTimerListener getActionListener() { return m_Listener; } public void setActionListener(ActivityTimerListener listener) { m_Listener = listener; } public void start() { if (m_Enabled) return; Enable(); } public boolean isFireOnlyOnce() { return m_FireOnce; } public void setFireOnlyOnce(boolean fireOnce) { m_FireOnce = fireOnce; } } In the activity, I have this onStart: #Override protected void onStart() { super.onStart(); m_Timer = new ActivityTimer(); m_Timer.setFireOnlyOnce(true); m_Timer.setActivity(this); m_Timer.setActionListener(this); m_Timer.setDelay(3000); m_Timer.start(); }
Here is a simple reliable way... Put the following code in your Activity, and the tick() method will be called every second in the UI thread while your activity is in the "resumed" state. Of course, you can change the tick() method to do what you want, or to be called more or less frequently. #Override public void onPause() { _handler = null; super.onPause(); } private Handler _handler; #Override public void onResume() { super.onResume(); _handler = new Handler(); Runnable r = new Runnable() { public void run() { if (_handler == _h0) { tick(); _handler.postDelayed(this, 1000); } } private final Handler _h0 = _handler; }; r.run(); } private void tick() { System.out.println("Tick " + System.currentTimeMillis()); } For those interested, the "_h0=_handler" code is necessary to avoid two timers running simultaneously if your activity is paused and resumed within the tick period.
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Timer; import java.util.TimerTask; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; import android.app.Activity; public class MainActivity extends Activity { CheckBox optSingleShot; Button btnStart, btnCancel; TextView textCounter; Timer timer; MyTimerTask myTimerTask; #Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); optSingleShot = (CheckBox)findViewById(R.id.singleshot); btnStart = (Button)findViewById(R.id.start); btnCancel = (Button)findViewById(R.id.cancel); textCounter = (TextView)findViewById(R.id.counter); btnStart.setOnClickListener(new OnClickListener(){ #Override public void onClick(View arg0) { if(timer != null){ timer.cancel(); } //re-schedule timer here //otherwise, IllegalStateException of //"TimerTask is scheduled already" //will be thrown timer = new Timer(); myTimerTask = new MyTimerTask(); if(optSingleShot.isChecked()){ //singleshot delay 1000 ms timer.schedule(myTimerTask, 1000); }else{ //delay 1000ms, repeat in 5000ms timer.schedule(myTimerTask, 1000, 5000); } }}); btnCancel.setOnClickListener(new OnClickListener(){ #Override public void onClick(View v) { if (timer!=null){ timer.cancel(); timer = null; } } }); } class MyTimerTask extends TimerTask { #Override public void run() { Calendar calendar = Calendar.getInstance(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a"); final String strDate = simpleDateFormat.format(calendar.getTime()); runOnUiThread(new Runnable(){ #Override public void run() { textCounter.setText(strDate); }}); } } } .xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="#dimen/activity_vertical_margin" android:paddingLeft="#dimen/activity_horizontal_margin" android:paddingRight="#dimen/activity_horizontal_margin" android:paddingTop="#dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:autoLink="web" android:text="http://android-er.blogspot.com/" android:textStyle="bold" /> <CheckBox android:id="#+id/singleshot" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Single Shot"/>
If you have delta time already. public class Timer { private float lastFrameChanged; private float frameDuration; private Runnable r; public Timer(float frameDuration, Runnable r) { this.frameDuration = frameDuration; this.lastFrameChanged = 0; this.r = r; } public void update(float dt) { lastFrameChanged += dt; if (lastFrameChanged > frameDuration) { lastFrameChanged = 0; r.run(); } } }
I Abstract Timer away and made it a separate class: Timer.java import android.os.Handler; public class Timer { IAction action; Handler timerHandler = new Handler(); int delayMS = 1000; public Timer(IAction action, int delayMS) { this.action = action; this.delayMS = delayMS; } public Timer(IAction action) { this(action, 1000); } public Timer() { this(null); } Runnable timerRunnable = new Runnable() { #Override public void run() { if (action != null) action.Task(); timerHandler.postDelayed(this, delayMS); } }; public void start() { timerHandler.postDelayed(timerRunnable, 0); } public void stop() { timerHandler.removeCallbacks(timerRunnable); } } And Extract main action from Timer class out as IAction.java public interface IAction { void Task(); } And I used it just like this: MainActivity.java public class MainActivity extends Activity implements IAction{ ... Timer timerClass; #Override protected void onCreate(Bundle savedInstanceState) { ... timerClass = new Timer(this,1000); timerClass.start(); ... } ... int i = 1; #Override public void Task() { runOnUiThread(new Runnable() { #Override public void run() { timer.setText(i + ""); i++; } }); } ... } I Hope This Helps 😊👌
I use this way: String[] array={ "man","for","think" }; int j; then below the onCreate TextView t = findViewById(R.id.textView); new CountDownTimer(5000,1000) { #Override public void onTick(long millisUntilFinished) {} #Override public void onFinish() { t.setText("I "+array[j] +" You"); j++; if(j== array.length-1) j=0; start(); } }.start(); it's easy way to solve this problem.