I have a simple stopwatch code piece. Thread is running in custom class, it connects to the main activity via Interface
public class MainActivity extends AppCompatActivity implements MainActivityInteractionInterface{
public static boolean isRunning = false;
Stopwatch stopWatch;
private TextView textViewMilliSeconds;
private TextView textViewSeconds;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewMilliSeconds = findViewById(R.id.textViewStopwatchMilliseconds);
textViewSeconds = findViewById(R.id.textViewStopwatchSeconds);
stopWatch = new Stopwatch(this, getApplicationContext());
stopWatch.runThread();
}
#Override
public void updateUI() {
String time = String.format(Locale.getDefault(), "%03d", stopWatch.getMilliseconds());
textViewMilliSeconds.setText(time);
String timeSeconds = String.format(Locale.getDefault(), "%02d", stopWatch.getSeconds());
textViewSeconds.setText(timeSeconds);
}
public void startTimer(View view) {
isRunning = !isRunning;
}
public class Stopwatch {
private int milliseconds = 0;
private int seconds = 0;
public int getMilliseconds() {
return milliseconds;
}
public int getSeconds() {
return seconds;
}
private MainActivityInteractionInterface interactionInterface;
private Context applicationContext;
public Stopwatch(MainActivityInteractionInterface interactionInterface, Context applicationContext){
this.interactionInterface = interactionInterface;
this.applicationContext = applicationContext;
}
public void runThread(){
final Handler handler = new Handler();
handler.post(new Runnable(){
#Override
public void run(){
if(isRunning) {
milliseconds++;
if (milliseconds == 1000) {
milliseconds = 0;
seconds++;
if(seconds == 60){
seconds = 0;
}
}
}
interactionInterface.updateUI();
handler.postDelayed(this, 1);
}
});
}
handler should update every 1 millisec, when there is 1000 milliseconds, 1 second passes by
If I set handler.postDelayed delay anything below 15 reaching 1000 milliseconds would take exactly 18 seconds, why?
I don't know why it would take up to 18seconds, but I can tell you this: Android refresh the UI every 16msec (to have a rate of 60fps), so setting the handler to updateUI in a lesser time would make no sense and maybe also interfier with it.
In my humble opinion, make it to update in 20msec and change the counter values according, like this:
handler.post(new Runnable(){
#Override
public void run(){
if(isRunning) {
milliseconds++;
if (milliseconds == 50) {
milliseconds = 0;
seconds++;
if(seconds == 60){
seconds = 0;
}
}
}
interactionInterface.updateUI();
handler.postDelayed(this, 20);
}
});
Look at the second argument of handler.postDelayed(this, 1);
Change it according to the way you increment your milliseconds.
I'm working on making my first Android App, and I cannot get the text to speech to work.
The gist of the app: user selects the time they want to set an alarm (using a TimePicker), then the app calculates the amount of time left, continuously updating the amount of time left.
I want the use the text to speech engine to verbally update the user at 5 minute intervals on how much time they have left.
Everything compiles and runs without error, but the text to speech just doesn't do anything. I've looked for days to find out how to properly initialize the TextToSpeech class in java, but everything I find seems to initialize it differently on a case by case basis.
After trying multiple different implementations, all with the same result, I decided to just make a separate inner class to make editing and trying new things easier, and I can just make a Voice class and call methods on it.
I've only been coding in Java for a few months, and this is my first Android App, so I am having a lot of trouble sorting through this on my own.
Below is the separate (inner/nested) class that I am using to initialize the TextToSpeech class:
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}
Here is the rest of the code in the activity ( I use a separate activity to display the countdown)
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.AppCompatActivity;
import android.os.*;
import android.widget.*;
import java.util.*;
import java.lang.*;
public class TimerActivity extends AppCompatActivity{
private int alarmHour = MainActivity.alarmHour;
private int alarmMinute = MainActivity.alarmMinute;
private Calendar alarmTime;
private Calendar currentTime;
private TextView timerText;
private TextView lateText;
private int hoursLeft;
private int minutesLeft;
private long difference;
private long calculatedMinutes;
private boolean late = false;
private String lateMessageString = "LATE!";
private String timeRemainingString = "remaining";
private Handler handler = new Handler();
private TextToSpeech tts;
private double pitch = 1;
private double speed = 1;
private int MY_DATA_CHECK_CODE = 0;
private Voice voice;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
voice = new Voice();
voice.say("This is some bullshit.");
initializeTimer();
}
private void initializeTimer () {
voice.say("Yes, hello. Is it me you're looking for?");
timerText = (TextView) findViewById(R.id.timerText);
lateText = (TextView) findViewById(R.id.lateText);
setAlarm();
calculateTimeLeft();
String timerString = getTimerString();
timerText.setText(timerString);
if (late) {
lateText.setText(lateMessageString);
}
else {
lateText.setText(timeRemainingString);
}
Timer timer = new Timer();
timer.schedule(new UpdateTimer(),100,60000);
}
private class UpdateTimer extends TimerTask {
public void run() {
handler.post(new Runnable() {
public void run() {
calculateTimeLeft();
String timerString = getTimerString();
timerText.setText(timerString);
if (late) {
lateText.setText(lateMessageString);
}
else {
lateText.setText(timeRemainingString);
}
}
});
}
}
private void setAlarm() {
alarmTime = Calendar.getInstance();
currentTime = Calendar.getInstance();
alarmTime.setTimeInMillis(System.currentTimeMillis());
alarmTime.set(Calendar.HOUR_OF_DAY, alarmHour);
alarmTime.set(Calendar.MINUTE, alarmMinute);
// If alarm is set for the past, then set the alarm for the next day at the specified time
if (alarmTime.getTimeInMillis() - System.currentTimeMillis() < 0) {
alarmTime.set(Calendar.DAY_OF_YEAR, alarmTime.get(Calendar.DAY_OF_YEAR) + 1);
}
}
private void calculateTimeLeft() {
currentTime.setTimeInMillis(System.currentTimeMillis());
difference = alarmTime.getTimeInMillis() - System.currentTimeMillis();
long seconds = difference/1000; // convert to seconds
long calculatedHours = seconds / 3600; // Find the number of hours until alarm
calculatedMinutes = (seconds % 3600) / 60; // Use mod to remove the number of hours, leaving only seconds since the last hour, then divide by 60 to get minutes
hoursLeft = (int)Math.abs(calculatedHours); // Get the absolute value of the time left for the string
minutesLeft = (int)Math.abs(calculatedMinutes); // Absolute value of the minutes for string use
}
private String getTimerString() {
// Format the string showing the time remaining
String timeLeftString;
if (hoursLeft == 0) {
timeLeftString = "";
}
else if (hoursLeft == 1) {
timeLeftString = hoursLeft + "hr ";
}
else {
timeLeftString = hoursLeft +"hrs ";
}
if (hoursLeft == 0) {
timeLeftString += minutesLeft;
}
/*
else if (minutesLeft < 10 && calculatedMinutes > 0) {
timeLeftString += "0" + minutesLeft;
}
*/
else {
timeLeftString += minutesLeft;
}
if (calculatedMinutes >= 0 && hoursLeft > 0) {
timeLeftString += " mins";
}
else if (calculatedMinutes > 0) {
timeLeftString += " mins";
}
else if (difference <= 0) {
late = true;
}
return timeLeftString;
}
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
I think you can't hear any voices that you want.
Because TextToSpeech class can't say immediately after you invoke constructor.
TextToSpeech class instance need to connect to system TTS service when it is initializing.
And if the instance is success to connect to service, onInit of TextToSpeech.OnInitListener will be activated!
So, you can hear the voice after onInit function is done. Try to move your voice.say functions at onInit function.
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
// try it!
voice.say("Can you hear this sentence?");
// If you want to another "say", check this log.
// Your voice will say after you see this log at logcat.
Log.i("TAG", "TextToSpeech instance initialization is finished.");
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}
I'm a novice in Java (Less than 3 months experience), and for a project I've been working on I need to create a timer.
I've done this before, however I do not know how to do one thing.
I want to start a timer when a second timer ends. What I mean by this is that instead of using a start/stop button to start a timer, I want to have a second timer (that starts at 3 seconds) determine when the first timer starts. For example, if the first timer is at 30 seconds, it will start counting down when the second timer finishes counting down from 3-0.
I know there has to be other classes or methods/listeners to do this, but as I've stated earlier, it's my first time ever working with Java (I normally use C++).
Any help/guidance/code on how to achieve this would be awesome. Here is the code I was toying around with to try and achieve this.
Java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.os.CountDownTimer;
public class Timer extends AppCompatActivity
{
TextView timer;
TextView timerStart;
Button multi;
int track;
int seconds;
CountDownTimer countDownTimer;
CountDownTimer start;
View.OnClickListener btnListen = new View.OnClickListener(){
#Override
public void onClick(View v)
{
switch(v.getId())
{
case R.id.multi : start();
break;
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
timer = (TextView) findViewById(R.id.timer);
timerStart = (TextView) findViewById(R.id.timerStart);
multi = (Button) findViewById(R.id.multi);
multi.setOnClickListener(btnListen);
multi.setText("Start");
}
public void start_timer()
{
track = 3;
start = new CountDownTimer(3*1000,1000) {
#Override
public void onTick(long millisUntilFinished) {
timerStart.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
timerStart.setText("Begin");
track = 0;
}
}.start();
seconds = 30;
if (timerStart.getText().equals("Begin"))
{
start.cancel();
countDownTimer = new CountDownTimer(30 * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timer.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
timer.setText("BEEP");
}
}.start();
}
else
{
System.out.println("Nothing");
}
}
public void start()
{
start_timer();
/*seconds = 30;
if (timerStart.getText().equals("Begin"))
{
countDownTimer = new CountDownTimer(seconds * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timer.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
timer.setText("BEEP");
}
}.start();
}*/
}
}
Again, this is just something I'm toying around with. If there is a different way to do this (Like using a Runnable or Handler), then I'm open to it. My goal is to learn Java.
How about this? I modified CountDownTimer to enable to be chained.
public abstract class ChainedCountDownTimer {
/**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture;
/**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval;
private long mStopTimeInFuture;
/**
* boolean representing if the timer was cancelled
*/
private boolean mCancelled = false;
/**
* First timer in chaining
*/
private ChainedCountDownTimer first;
/**
* Next timer
*/
private ChainedCountDownTimer next;
/**
* #param millisInFuture The number of millis in the future from the call
* to {#link #start()} until the countdown is done and {#link #onFinish()}
* is called.
* #param countDownInterval The interval along the way to receive
* {#link #onTick(long)} callbacks.
*/
public ChainedCountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
first = this;
}
/**
* Cancel the countdown.
*/
public synchronized final void cancel() {
first.mCancelled = true;
mHandler.removeMessages(MSG);
}
public void start() {
first.startInternal();
}
/**
* Start the countdown.
*/
public synchronized final ChainedCountDownTimer startInternal() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
if (next != null) {
next.startInternal();
}
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}
/**
* Callback fired on regular interval.
* #param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished);
/**
* Callback fired when the time is up.
*/
public abstract void onFinish();
public ChainedCountDownTimer setNext(ChainedCountDownTimer next) {
this.next = next;
next.first = this.first;
return this.next;
}
private static final int MSG = 1;
// handles counting down
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
synchronized (ChainedCountDownTimer.this) {
if (first.mCancelled) {
return;
}
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
if (next != null) {
next.startInternal();
}
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft);
// take into account user's onTick taking time to execute
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
// special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
}
You can use it like this.
ChainedCountDownTimer timer1 = new ChainedCountDownTimer(3 * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.d(TAG, "timer1 onTick");
}
#Override
public void onFinish() {
Log.d(TAG, "timer1 onFinish");
}
};
ChainedCountDownTimer timer2 = new ChainedCountDownTimer(30 * 1000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.d(TAG, "timer2 onTick");
}
#Override
public void onFinish() {
Log.d(TAG, "timer2 onFinish");
}
};
timer1.setNext(timer2).start();
I am learning the android development which now I am making a simple timer which I needs a handler to keep it running. If I put the handler inside the main activity, everything goods but I would like to put the method outside the main activity so I can reuse the codes and should be more flexible if I would like to change anything.
here is my code:
*public class Timer{
public void runTimer(TextView view, int seconds, boolean running){
TextView timerTextView = (TextView) view;
Handler handler = new Handler();
MyRunnable r = new MyRunnable(handler,view,seconds,running);
handler.post(r);
}
}
class MyRunnable implements Runnable {
private TextView view;
private int seconds;
private boolean running;
private Handler handler;
public MyRunnable(Handler handler, TextView view, int seconds, boolean running){
this.handler= handler;
this.view =view;
this.seconds = seconds;
this.running = running;
}
public void run(){
TextView timerTextView = (TextView) view;
int hours = seconds/3600;
int minutes = (seconds%3600)/60;
int secs = seconds%60;
String time = String.format("%d:%02d:%02d",hours,minutes,secs);
timerTextView.setText(time);
if (running){
seconds++;
}
handler.postDelayed(this,100);
}
}*
And I created an object in the main activity to call this function. The app can run but the timer doesn't work properly. It only runs the first time but then stop at all. It doesn't keep running. Do you know where is the problem? thanks for your help first!
Main code:
*package com.mad.chapter4;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class StopWatchActivity extends AppCompatActivity {
private Timer timer = new Timer();
private int seconds = 0;
private boolean running = false;
private boolean wasRunning;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stop_watch);
TextView ttv = (TextView) findViewById(R.id.timerTextView);
if(savedInstanceState!=null){
seconds = savedInstanceState.getInt("seconds");
running = savedInstanceState.getBoolean("running");
wasRunning = savedInstanceState.getBoolean("wasRunning");
}
seconds = timer.runTimer(ttv,seconds,running);
}
public void onSaveInstanceState (Bundle savedInstanceState){
savedInstanceState.putInt("seconds",seconds);
savedInstanceState.putBoolean("running",running);
savedInstanceState.putBoolean("wasRunning",wasRunning);
}
protected void onStop(){
super.onStop();
wasRunning = running;
running = false;
}
protected void onStart(){
super.onStart();
if(wasRunning){
running = true;
}
}
public void onClickStartButton(View view){
running = true;
}
public void onClickStopButton (View view){
running = false;
}
public void onClickResetButton (View view){
seconds = 0;
running = false;
}
// public void runTimer(){
//
// final TextView timerTextView = (TextView) findViewById(R.id.timerTextView);
// final Handler handler = new Handler();
//
// Runnable r = new Runnable(){
// #Override
// public void run(){
// int hours = seconds/3600;
// int minutes = (seconds%3600)/60;
// int secs = seconds%60;
// String time = String.format("%d:%02d:%02d",hours,minutes,secs);
// timerTextView.setText(time);
// if (running){
// seconds++;
// }
// handler.postDelayed(this,100);
// }
// };
//
// handler.post(r);
//
//
// }
}*
From the way I see it your running and wasRunning are never set to true which in turn is not updating your UI only first time but not after that. Try setting running and wasRunning to true before you call timer.runTimer(ttv, seconds, running) in onCreate. I think when you were calling this code in activity you were making call to onClickStartButton(View view) which did set the running flag to true and was updating your UI correctly.
Also, your runTimer functions does not return anything but you in your code you are assigning this function result to an int. Is that a copy/paste error?
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.