Stop a stopwatch in Android - java

I've made a custom stop watch which showing hours:minuted:seconds.Controls are given by START and STOP buttons.But, there is a problem when stopping the stopwatch.It didn't stop when the STOP button is clicked. Anybody please suggest me the right solution.
package com.example.mystopwatch;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class StopwatchActivity extends Activity {
private TextView textViewTimer;
private Button BtnStart,BtnStop;
private Handler mHandler = new Handler();
private long startTime;
private long elapsedTime;
private final int REFRESH_RATE = 100;
private String hours,minutes,seconds,milliseconds;
private long secs,mins,hrs,msecs;
private boolean stopped = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stopwatch);
BtnStart=(Button)findViewById(R.id.startbtn);
BtnStop=(Button)findViewById(R.id.stopbtn);
BtnStart.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Runnable startTimer1 = new Runnable()
{
public void run()
{
elapsedTime = System.currentTimeMillis() - startTime; updateTimer(elapsedTime);
mHandler.postDelayed(this,REFRESH_RATE);
}
};
if(stopped)
{
startTime = System.currentTimeMillis() - elapsedTime;
}
else
{
startTime = System.currentTimeMillis();
}
mHandler.removeCallbacks(startTimer1);
mHandler.postDelayed(startTimer1, 0);
}
});
BtnStop.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Runnable startTimer2 = new Runnable()
{
public void run()
{
elapsedTime = System.currentTimeMillis() - startTime; updateTimer(elapsedTime);
mHandler.postDelayed(this,REFRESH_RATE);
}
};
mHandler.removeCallbacks(startTimer2);
stopped = true;
}
});
}
private void updateTimer(long time) {
// TODO Auto-generated method stub
secs = (long)(time/1000);
mins = (long)((time/1000)/60);
hrs = (long)(((time/1000)/60)/60);
secs = secs % 60;
seconds=String.valueOf(secs);
if(secs == 0)
{
seconds = "00";
}
if(secs <10 && secs > 0)
{
seconds = "0"+seconds;
}
mins = mins % 60;
minutes=String.valueOf(mins);
if(mins == 0){ minutes = "00";
}
if(mins <10 && mins > 0)
{
minutes = "0"+minutes;
}
hours=String.valueOf(hrs);
if(hrs == 0)
{
hours = "00";
}
if(hrs <10 && hrs > 0)
{
hours = "0"+hours;
}
milliseconds = String.valueOf((long)time);
if(milliseconds.length()==2)
{
milliseconds = "0"+milliseconds;
}
if(milliseconds.length()<=1)
{ milliseconds = "00";
}
milliseconds = milliseconds.substring(milliseconds.length()-3, milliseconds.length()-2);
((TextView)findViewById(R.id.timertxt)).setText(hours + ":" + minutes + ":" + seconds);
}
}

Most of the code in your BtnStop.setOnClickListener is actually useless. You define a Runnable called startTimer2, but for what purpose? You never use that Runnable except in the call to mHandler.removeCallbacks(startTimer2);. That will remove any calls that were made to it before, but since you never made any, this does not do anything.
The only thing your method does when you click the stop button is to set the boolean flag stopped to true. But there is no periodic process checking that flag. The only time you check the flag is when the START button is pressed.
As a side note, your use of REFRESH_RATE is confusing. Setting a higher number will actually result in a lower refresh rate since postDelayed takes a duration. Consider renaming the variable or adding a division.

It can not stop since you don't check boolean stopped in your run method. Move it inside :
public void run() {
elapsedTime = System.currentTimeMillis() - startTime;
updateTimer(elapsedTime);
if(!stopped) {
mHandler.postDelayed(this, REFRESH_RATE);
}
}
and also consider declaring stopped as volatile as per suggestion in the comments.

there is whole task to start and stop , stopwatch just call :-- handler.sendEmptyMessage(MSG_STOP_TIMER); to stop stopwatch
Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_START_TIMER:
timer.start(); //start timer
handler.sendEmptyMessage(MSG_UPDATE_TIMER);
break;
case MSG_UPDATE_TIMER:
//timerText.setText(String.format("%1$tM:%1$tS",timer.getElapsedTimeMin(),timer.getElapsedTimeSecs()));
if ( timer.getElapsedTimeSecs() < 10)
{
if(timer.getElapsedTimeMin()<10){
timerText.setText("0" + timer.getElapsedTimeMin() + ":0" + timer.getElapsedTimeSecs());
}else{
timerText.setText("" + timer.getElapsedTimeMin() + ":0" + timer.getElapsedTimeSecs());
}
}
else{
if(timer.getElapsedTimeMin()<10){
timerText.setText("0" + timer.getElapsedTimeMin() + ":" + timer.getElapsedTimeSecs());
}else{
timerText.setText(timer.getElapsedTimeMin()+":"+ timer.getElapsedTimeSecs());
}
}
handler.sendEmptyMessageDelayed(MSG_UPDATE_TIMER,REFRESH_RATE); //text view is updated every second,
break; //though the timer is still running
case MSG_STOP_TIMER:
handler.removeMessages(MSG_UPDATE_TIMER); // no more updates.
timer.stop();//stop timer
timerText.setText("0"+timer.getElapsedTimeMin()+":0"+ timer.getElapsedTimeSecs());
break;
default:
break;
}
}
};

Related

Count Down Timer for a timer

I am trying to make a Pomodoro Timer (25 minutes work, 5 minutes break then repeat n times). But I can't find a way to let the break timer start automatically and then start again with the work timer (work timer = 00:10 - break timer = 00:03, i put these values so i can test faster). How can I fix this?
public class MainActivity extends AppCompatActivity {
TextView tvTimer, tvSessions;
ImageView ivStart, ivStop;
SeekBar seekBar;
CountDownTimer countDownTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTimer = findViewById(R.id.tvTimer);
tvSessions = findViewById(R.id.tvSessions);
ivStart = findViewById(R.id.ivStart);
ivStop = findViewById(R.id.ivStop);
seekBar = findViewById(R.id.seekBar);
seekBar.setMax(2500);
seekBar.setProgress(10);
seekBar.setVisibility(View.GONE);
tvTimer.setText("00:10");
}
// ON CLICK METHODS
public void startTimer(View v){
countDownTimer = new CountDownTimer(seekBar.getProgress() * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
breakTimer();
}
};
countDownTimer.start();
}
public void stopTimer(View v){
}
// UPDATE METHODS
private void breakTimer(){
seekBar.setProgress(3);
tvTimer.setText("00:03");
}
private void updateTimer(int progress){
int minutes = progress / 60;
int seconds = progress - minutes * 60;
String textMinutes = String.valueOf(minutes);
String textSeconds = String.valueOf(seconds);
if(seconds < 10) textSeconds = "0" + textSeconds;
if(minutes < 10) textMinutes = "0" + textMinutes;
tvTimer.setText(textMinutes + ":" + textSeconds);
}
}
Expected output:
00:10 -> 00:00 -> 00:03 -> 00:00 -> 00:10 and so on...
What about something like this. Using a flag to keep track of if the Timer is a rest timer or a pomodoro timer.
When the timer finishes, you check the flag to decide which timer to start next (and flip the flag so next time it does the opposite).
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
private static final int TICK_EVERY_SECOND = 1000;
private TextView tvTimer, tvSessions;
private ImageView ivStart, ivStop;
private SeekBar seekBar;
private CountDownTimer countDownTimer;
private boolean isRest = false;
private int userSelectedDurationSeconds = -1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTimer = findViewById(R.id.tvTimer);
tvSessions = findViewById(R.id.tvSessions);
ivStart = findViewById(R.id.ivStart);
ivStop = findViewById(R.id.ivStop);
seekBar = findViewById(R.id.seekBar);
seekBar.setMax(2500);
seekBar.setProgress(10);
seekBar.setVisibility(View.GONE);
tvTimer.setText("00:10");
}
// ON CLICK METHODS
public void startTimer(View v) {
isRest = false;
int durationSeconds = seekBar.getProgress();
userSelectedDurationSeconds = durationSeconds;
restartTimer(durationSeconds);
}
private void restartTimer(int durationSeconds) {
countDownTimer = new CountDownTimer(TimeUnit.SECONDS.toMillis(durationSeconds), TICK_EVERY_SECOND) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
breakTimer();
}
};
countDownTimer.start();
}
public void stopTimer(View v) {
}
// UPDATE METHODS
private void breakTimer() {
isRest = !isRest;
if(isRest) {
seekBar.setProgress(3);
tvTimer.setText("00:03");
restartTimer(3);
} else {
restartTimer(userSelectedDurationSeconds);
}
}
private void updateTimer(int progressInSeconds) {
int minutes = progressInSeconds / 60;
int seconds = progressInSeconds - minutes * 60;
String textMinutes = String.valueOf(minutes);
String textSeconds = String.valueOf(seconds);
if (seconds < 10) textSeconds = "0" + textSeconds;
if (minutes < 10) textMinutes = "0" + textMinutes;
tvTimer.setText(textMinutes + ":" + textSeconds);
}
}

How to make a timer which executes for certain amount of time

I'm in the middle of a Football Match Timer project. Basically, I'm looking for an implementation of a timer which starts after pushing a "START 1st half" button, counts to 45 minutes, than pauses and we are able to start it again pushing "START 2nd half"(it would be the same button, but its text would be changed through the whole match). Then it would count from 45 minutes to 90 minutes.
I've been trying to accomplish this using Handler(), Runnable() and onClickListener(), but it doesn't work at all for me :( Would you give me some suggestions about how to tackle this?
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
showTimeRemaining();
timerHandler.postDelayed(this, 500);
}
};
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button b = (Button) v;
startButton(v);
if (b.getText().equals("Mecz trwa")) {
timerHandler.removeCallbacks(timerRunnable);
b.setEnabled(true);
} else {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
b.setText("Mecz trwa");
b.setEnabled(false);
}
}
});
public void showTimeRemaining() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
timerTextView = (TextView) findViewById(R.id.time);
timerTextView.setText(String.format("%d:%02d", minutes, seconds));
}
Here are some of my suggestions.
First, encapsulate your Handler into a class called Timer. This way it's easier to manipulate your timers. Here is my version:
import android.os.Handler;
public class Timer {
private Handler handler;
private boolean paused;
private int interval;
private Runnable task = new Runnable () {
#Override
public void run() {
if (!paused) {
runnable.run ();
Timer.this.handler.postDelayed (this, interval);
}
}
};
private Runnable runnable;
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void startTimer () {
paused = false;
handler.postDelayed (task, interval);
}
public void stopTimer () {
paused = true;
}
public Timer (Runnable runnable, int interval, boolean started) {
handler = new Handler ();
this.runnable = runnable;
this.interval = interval;
if (started)
startTimer ();
}
}
Secondly, don't use System.currenTimeMillis. Use something more manipulatable. Create a variable of your own that stores how many seconds are left:
private int secondsLeft = 60 * 45;
You decrement this variable every second, until it reaches zero. Then, you stop the timer, change the button's text or whatever. This logic should be put into the Runnable used for the handler.
I would suggest to try using of CountDownTimer.
Refer here for documentation and usage:
https://developer.android.com/reference/android/os/CountDownTimer.html

How do i make a simple timer in java with a button click to start/stop the timer?

In android studio in the MainActivity in the onCreate i did:
timerValueRecord = (TextView) findViewById(R.id.timerValueRecord);
In strings.xml i added:
<string name="timerValRecord">Recording Time: 00:00:00</string>
In activity_main.xml i added:
<TextView
android:id="#+id/timerValueRecord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="20sp"
android:textColor="#000000"
android:layout_marginTop="315dp"
android:text="#string/timerValRecord" />
In the activity_main designer it looks like:
In the MainActivity i have a touch event:
#Override
public boolean onTouchEvent(MotionEvent event)
{
float eventX = event.getX();
float eventY = event.getY();
float lastdownx = 0;
float lastdowny = 0;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
lastdownx = eventX;
lastdowny = eventY;
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
byte[] response = null;
if (connectedtoipsuccess == true)
{
if (is_start == true)
{
response = Get(iptouse + "start");
is_start = false;
} else
{
textforthespeacch = "Recording stopped and preparing the file to be shared on youtube";
MainActivity.this.initTTS();
response = Get(iptouse + "stop");
is_start = true;
startuploadstatusthread = true;
servercheckCounter = 0;
}
if (response != null)
{
try
{
a = new String(response, "UTF-8");
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
if (a.equals("Recording started"))
{
status1.setText("Recording");
}
if (a.equals("Recording stopped and preparing the file to be shared on youtube"))
{
status1.setText("Recording Stopped");
}
}
});
textforthespeacch = a;
MainActivity.this.initTTS();
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
Logger.getLogger("MainActivity(inside thread)").info(a);
}
}
}
});
t.start();
return true;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
default:
return false;
}
return true;
}
What i want to do is when in the touch event it's true after this line:
if (is_start == true)
Start the timer and display on the timerValueRecord the time running including milliseconds seconds and minutes until the user touch again and then it's getting to the stop part and then to stop the timer.
The problem is how to build the timer at all and how to stop and start it.
You can try this below Code:
public class ShowTimer {
private long startTime = 0L;
private Handler customHandler = new Handler();
long timeInMilliseconds = 0L;
long timeSwapBuff = 0L;
long updatedTime = 0L;
public void StartTimer() {
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public void StopTimer() {
timeSwapBuff += timeInMilliseconds;
customHandler.removeCallbacks(updateTimerThread);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
updatedTime = timeSwapBuff + timeInMilliseconds;
int secs = (int) (timeInMilliseconds / 1000);
int mins = secs / 60;
secs = secs % 60;
int hours = mins / 60;
mins = mins % 60;
//int milliseconds = (int) (updatedTime % 1000);
//+ ":" + String.format("%03d", milliseconds)
String timer = "" + String.format("%02d", hours) + ":" + String.format("%02d", mins) + ":" + String.format("%02d", secs);
//set yout textview to the String timer here
customHandler.postDelayed(this, 1000);
}
};
You can use StartTimer() and StopTimer() function where you want to start or stop the timer:
try this way
public class AndroidTimerTaskExample extends Activity {
Timer timer;
TimerTask timerTask;
//we are going to use a handler to be able to run in our TimerTask
final Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
//onResume we start our timer so it can start when the app comes from the background
startTimer();
}
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, after the first 5000ms the TimerTask will run every 10000ms
timer.schedule(timerTask, 5000, 10000); //
}
public void stoptimertask(View v) {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
//use a handler to run a toast that shows the current timestamp
handler.post(new Runnable() {
public void run() {
//get the current timeStamp
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
final String strDate = simpleDateFormat.format(calendar.getTime());
//show the toast
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(getApplicationContext(), strDate, duration);
toast.show();
}
});
}
};
}
}

How to save timer class start time?

I am implementing countup concept in my project..it contains 3 question buttons..if user clicks on first button count up is start. Whenever he presses the 2nd question.. count up should reset. If user returns to first button then count up should update where it paused..
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long systemTime = System.currentTimeMillis();
Log.d("System Time", String.valueOf(systemTime));
long millis = systemTime - startTime;
Log.d("millis", String.valueOf(millis));
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
qstimer.setText(String.format("%d:%02d", minutes, seconds));
timerHandler.postDelayed(this, 500);
}
};
try this
In your first button(ON) paste this code and in second button(OFF) paste the same code but instead of "i==0" take another variable
if(i == 0){
pauseTime = timeSwap+= timeInMillies;
timeMap.put(keyQuestion, pauseTime);
keyQuestion = q1.getText().toString();
timerStart();
i = 1;
}
else if(i == 1){
myHandler.removeCallbacks(updateTimerMethod);
pauseTime = timeSwap+= timeInMillies;
timeMap.put(keyQuestion, pauseTime);
keyQuestion = q1.getText().toString();
timeSwap = 0L;
timeSwap += timeMap.get(keyQuestion);
startTime = SystemClock.uptimeMillis();
myHandler.postDelayed(updateTimerMethod, 0);
}
Hope it helps.
Add an OnCLickListener to your buttons :
private OnClickListener mOnClickListener = new OnClickListener()
{
#Override
public void onClick(View v)
{
if (mOnButtonClickListener != null)
{
switch (v.getId())
{
case R.id.on:
startTime = SystemClock.elapsedRealtime();
timerHandler.post(timerRunnable);
break;
case R.id.off:
timerHandler.removeCallbacks(timerRunnable);
break;
}
}
}
};
If you want your OFF button to PAUSE the timer you have to store the pause start time and the total paused time:
private OnClickListener mOnClickListener = new OnClickListener()
{
#Override
public void onClick(View v)
{
if (mOnButtonClickListener != null)
{
switch (v.getId())
{
case R.id.on:
if(paused)
{
pausedTime += SystemClock.elapsedRealtime()-pauseStartTime;
}
else
{
startTime = SystemClock.elapsedRealtime();
}
timerHandler.post(timerRunnable);
break;
case R.id.off:
pauseStartTime = SystemClock.elapsedRealtime();
timerHandler.removeCallbacks(timerRunnable);
break;
}
}
}
};
And in your runnable :
long millis = time - startTime - pausedTime;
Hope it helps

CountDownTimer Android issue

I'm trying to implement a CountDownTimer in an Android Application. This timer will, while running, countdown from a value, than reset, than countdown from a different value. Switching back and force between values until either a set number of rounds have elapsed or the stop button has been pressed. I can get the CountDownTimer samples to work, but I guess I'm missing something here. Below is the applicable button press code;
CounterState state = CounterState.WORKOUT;
private WorkoutTimer workoutTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.workout_stopwatch);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set up OnClickListeners
((Button) findViewById(R.id.start_button)).setOnClickListener(this);
((Button) findViewById(R.id.stop_button)).setOnClickListener(this);
((Button) findViewById(R.id.reset_button)).setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.start_button:
if (!timer_running) {
timer_running = true;
Log.d(TAG, "clicked on Start Button");
// If the state is unknown, set it to Workout first
int State = state.getStateValue();
if (State == 0) {
state.setStateValue(1);
}
workoutTimer.start();
}
break;
case R.id.stop_button:
Log.d(TAG, "clicked on Stop Button");
if (timer_running); {
timer_running = false;
workoutTimer.cancel();
}
break;
private class WorkoutTimer extends CountDownTimer{
public WorkoutTimer(long interval) {
super(getThisTime(), interval);
Log.d(TAG, "WorkoutTimer Constructed...");
}
TextView digital_display = (TextView) findViewById(R.id.digital_display);
TextView numOfRounds = (TextView) findViewById(R.id.number_of_rounds);
public void onFinish() {
int State = state.getStateValue();
int roundsLeft = 0;
if (State == 1) {
state.setStateValue(2);
} else {
state.setStateValue(1);
}
decrementRounds();
try {
roundsLeft = Integer.parseInt(numOfRounds.getText().toString());
} catch(NumberFormatException nfe) {
roundsLeft = 999;
}
if (roundsLeft > 0 || roundsLeft != 999) {
workoutTimer.start();
}
}
public void onTick(long millisUntilFinished) {
final long minutes_left = ((millisUntilFinished / 1000) / 60);
final long seconds_left = (millisUntilFinished / 1000) - (minutes_left * 60);
final long millis_left = millisUntilFinished % 100;
String time_left = String.format("%02d:%02d.d", minutes_left, seconds_left,
millis_left);
digital_display.setText(time_left);
}
}
private long getThisTime() {
long time = 0;
TextView workout_time = (TextView) findViewById(R.id.workout_time);
TextView rest_time = (TextView) findViewById(R.id.rest_time);
switch(state) {
case WORKOUT:
try {
time = Integer.parseInt(workout_time.getText().toString());
} catch(NumberFormatException nfe) {
time = 999;
}
// time = 90;
Log.d(TAG, "Workout time = " + time);
break;
case REST:
try {
time = Integer.parseInt(rest_time.getText().toString());
} catch(NumberFormatException nfe) {
time = 999;
}
// time = 30;
Log.d(TAG, "Rest time = " + time);
break;
case UNKNOWN:
time = 0;
break;
}
return time;
}
Everything starts up okay, but crashes when I click either button. If I comment out my calls to the workoutTimer, no crash. I never see my log in the constructor of the workoutTimer class, so obviously I'm missing something here. Any help would be appreciated.
-Ian
You have not initialized your workoutTimer. You need to add the following line in your onCreate method.
workoutTimer = new WorkoutTimer(...);

Categories

Resources