Stopwatch with sound at a certain time - java

I have a project that contains a timer, I'm trying to put an alarm or music to play when the time of 12 minutes is reached. How could this be possible? If anyone can help me, I'm a beginner.
Buttons that start, pause, and reset the timer
switch (view.getId()) {
case R.id.bt_control:
if (btControl.getText().equals("Play")) {
this.startService(intent);
cmPasstime.setBase(SystemClock.elapsedRealtime());
cmPasstime.start();
btControl.setText("Stop");
} else if (btControl.getText().equals("Stop")) {
this.stopService(intent);
cmPasstime.stop();
btControl.setText("Play");
} else if (btControl.getText().equals("Play")) {
this.startService(intent);
cmPasstime.start();
btControl.setText("Stop");
}
break;
case R.id.bt_reset:
reset();
break;
}
Stopwatch
#Override
public void onChronometerTick(Chronometer arg0) {
seconds++;
cmPasstime.setText(formatseconds());
}
public String formatseconds() {
String hh = seconds / 3600 > 9 ? seconds / 3600 + "" : "0" + seconds
/ 3600;
String mm = (seconds % 3600) / 60 > 9 ? (seconds % 3600) / 60 + ""
: "0" + (seconds % 3600) / 60;
String ss = (seconds % 3600) % 60 > 9 ? (seconds % 3600) % 60 + ""
: "0" + (seconds % 3600) % 60;
return hh + " : " + mm + " : " + ss;
}
Reset
private void reset() {
tvPasstime.setText("00:00:00");
cmPasstime.setBase(SystemClock.elapsedRealtime());
cmPasstime.stop();
btControl.setText("Play");
}

Try to use Firebase JobDispatcher, this library will schedule job in background to do something at specified time.
https://github.com/firebase/firebase-jobdispatcher-android

Related

Problems with Chronometer and ViewModel

Pressing the button changes the chronometerStateLData and the Chronometer starts, after turning the screen Observer executes the code again, but the Chronometer does not start.
viewModel.chronometerStateLData.observe(viewLifecycleOwner, Observer {
Utils.setSettingChronometer(binding.timerRecord)
binding.timerRecord.start()
})
public static void setSettingChronometer(Chronometer chronometer) {
chronometer.setOnChronometerTickListener(chronometer1 -> {
long time = SystemClock.elapsedRealtime() - chronometer1.getBase();
int h = (int) (time / 3600000);
int m = (int) (time - h * 3600000) / 60000;
int s = (int) (time - h * 3600000 - m * 60000) / 1000;
String t = (h < 10 ? "0" + h : h) + ":" + (m < 10 ? "0" + m : m) + ":" + (s < 10 ? "0" + s : s);
chronometer1.setText(t);
});
}
I solved my problem. I didn't check if (savedInstanceState == null) when I created my fragment, so every time I flipped the screen a new fragment was created.

Timer shows 010:00 after 10 minutes instead of 10:00

What do I have to change so that the timer is showing 10:00 after 10 minutes instead of 010:00. I know a bit how to solve it but it doesn't solve the original problem -- if delete the "0" from (textTimer.setText("0" + minutes + ":") it shows 0:00 when its under 10. How do I make it to show 10:00 after 10 minutes and 00:00 before 10 mins. Thanks
public void run() {
timeInMillies = SystemClock.uptimeMillis() - startTime;
finalTime = timeSwap + timeInMillies;
int seconds = (int) (finalTime / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
int milliseconds = (int) (finalTime % 1000);
textTimer.setText("0" + minutes + ":"
+ String.format("%02d", seconds));
myHandler.postDelayed(this, 0);
}
I'm not entirely sure why you're not formatting the entire string
textTimer.setText(String.format("%02d:%02d", minutes, seconds));

Converting seconds to hours, minutes and seconds

I want to use count up timer in android for long hours...
Currently, I am using this code, but after some hours, say after 10 hours, the format goes like 10 : 650 :56 (hh:mm:ss)... for lesser time, it works perfectly...
private Runnable updateTimerMethod = new Runnable() {
public void run() {
timeInMillies = SystemClock.uptimeMillis() - startTime;
finalTime = timeSwap + timeInMillies;
int seconds = (int) (finalTime / 1000);
int minutes = seconds / 60;
int hours = minutes / 60;
seconds = seconds % 60;
int milliseconds = (int) (finalTime % 1000);
String timer = ("" + String.format("%02d", hours) + " : "
+ String.format("%02d", minutes) + " : "
+ String.format("%02d", seconds));
myHandler.postDelayed(this, 0);
sendLocalBroadcast(timer);
}
};
Your code for minutes is almost right, but you have to modulus it by 60 just like you do for seconds. Otherwise your value is going to still include all the hours.
Use this function:
private static String timeConversion(int totalSeconds) {
final int MINUTES_IN_AN_HOUR = 60;
final int SECONDS_IN_A_MINUTE = 60;
int seconds = totalSeconds % SECONDS_IN_A_MINUTE;
int totalMinutes = totalSeconds / SECONDS_IN_A_MINUTE;
int minutes = totalMinutes % MINUTES_IN_AN_HOUR;
int hours = totalMinutes / MINUTES_IN_AN_HOUR;
return hours + " : " + minutes + " : " + seconds;
}
You can found other solution in:
https://codereview.stackexchange.com/q/62713/69166

Calculation of times off milliseconds to time

This code below is used to format milliseconds. The calculations are off by a long shot. I need some help with it. Output of my code is below as well as the milliseconds into a Date class.
public static void main(String[] args) {
System.out.println("Wrong Time: " + getTime(999999999 * 599));
}
//Being called into this method is milliseconds = 598999999401
public static String getTime(long miliseconds) {
int years = (int) ((miliseconds / (1000*60*60*24*7*52*12)));
int months = (int) (miliseconds / (1000*60*60*24*7*52) % 12);
int weeks = (int) ((miliseconds / (1000*60*60*24*7)) % 52);
int days = (int) ((miliseconds / (1000*60*60*24)) % 7);
int hours = (int) ((miliseconds / (1000*60*60)) % 24);
int minutes = (int) ((miliseconds / (1000*60)) % 60);
int seconds = (int) (miliseconds / 1000) % 60;
Date date = new Date(598999999401L);//This gets the real time
System.out.println("Right Time: " + date.getYear() + " years " + (int)(date.getMonth() % 12) + " months " + (int)(date.getDay() % 52) + " weeks "
+ (int)(date.getDay() % 7) + " days " + (int)(date.getHours() % 24) + " hours " + (int)(date.getMinutes() % 60) + " minutes " +
+ (int)(date.getSeconds() % 60) + " seconds");
return (years <= 0 ? "" : years + " year" + (years != 1 ? "s" : "")) +
(months <= 0 ? "" : " " + months + " month" + (months != 1 ? "s" : "")) +
(weeks <= 0 ? "" : " " + weeks + " week" + (weeks != 1 ? "s" : "")) +
(days <= 0 ? "" : " " + days + " day" + (days != 1 ? "s" : "")) +
(hours <= 0 ? "" : " " + hours + " hour" + (hours != 1 ? "s" : "")) +
(minutes <= 0 ? "" : " " + minutes + " minute" + (minutes != 1 ? "s" : "")) +
(seconds <= 0 ? "" : " " + seconds + " second" + (seconds != 1 ? "s" : ""));
}
Correct Output(Date class)
Right Time: 88 years 11 months 6 weeks 6 days 14 hours 53 minutes 19 seconds
Wrong Output(My method)
Wrong Time: 1 month 3 weeks 2 days 3 hours 25 minutes 45 seconds
UPDATE 1 (NEW CALCULATIONS)(Still has logic errors):
int years = (int) ((miliseconds / (1000*60*60*24*7*4*12)));
int months = (int) (miliseconds / (1000*60*60*24*7*4) % 12);
int weeks = (int) ((miliseconds / (1000*60*60*24*7)) % 4);
int days = (int) ((miliseconds / (1000*60*60*24)) % 7);
int hours = (int) ((miliseconds / (1000*60*60)) % 24);
int minutes = (int) ((miliseconds / (1000*60)) % 60);
int seconds = (int) (miliseconds / 1000) % 60;
Two issues.
Your code seems to reflect a belief that there are 52 weeks in a month. These are the two lines at fault.
int years = (int) ((miliseconds / (1000*60*60*24*7*52*12)));
int months = (int) (miliseconds / (1000*60*60*24*7*52) % 12);
Also, you're using int where you should be using long. The maximum int number of milliseconds is just under 25 days, so you can never do date/time arithmetic with int.
One problem is int overflow since your main method is using int literals, not longs. Try:
System.out.println("Wrong Time: " + getTime(999999999L * 599L));
Also, don't use magic numbers. Use constants that make sense and that make your code self-commenting:
private static final int MILI_PER_SEC = 1000;
private static final int SEC_PER_MIN = 60;
private static final int MIN_PER_HR = 60;
private static final int HR_PER_DAY = 24;
private static final int DAYS_PER_YR = 365;
and then,
int years = (int) (miliseconds / (MILI_PER_SEC * SEC_PER_MIN * MIN_PER_HR *
HR_PER_DAY * DAYS_PER_YR));
Also, your calculations are all off. You shouldn't be using weeks in the year calculation at all. Use constants, have them make sense. And how do you know that the "correct" result is in fact correct? You are using deprecated code, and Date doesn't use miliseconds the way that you think that it does. It calculates the date relative to January 1, 1970, 00:00:00 GMT as per the Date API.

Format Stopwatch to display 00:00

I am experimenting with using a stopwatch in one of my apps and I have got it to where it will start counting seconds on start and stop counting on stop. My problem is that it will keep going on after 60 seconds. For example I get 120 seconds if I waited for two minutes.
So my question is how can I make it so once the seconds reached 60 the minutes would be increased by one and the seconds would start over?
So instead of :120 I would get 2:00. Here is the code I have:
final int MSG_START_TIMER = 0;
final int MSG_STOP_TIMER = 1;
final int MSG_UPDATE_TIMER = 2;
Stopwatch timer = new Stopwatch();
final int REFRESH_RATE = 100;
Handler mHandler = new Handler()
{
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MSG_START_TIMER:
timer.start();
mHandler.sendEmptyMessage(MSG_UPDATE_TIMER);
break;
case MSG_UPDATE_TIMER:
tvTextView.setText(":"+ timer.getElapsedTimeSecs());
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIMER,REFRESH_RATE);
break;
case MSG_STOP_TIMER:
mHandler.removeMessages(MSG_UPDATE_TIMER);
timer.stop();
tvTextView.setText("");
break;
default:
break;
}
}
};
Also are:
public void start(View v) {
mHandler.sendEmptyMessage(MSG_START_TIMER);
}
public void stop(View v) {
mHandler.sendEmptyMessage(MSG_STOP_TIMER);
}
By the way I looked at this question but his issue was with TimeSpan and if I understand correctly that is different from Stopwatch(correct me if I am wrong). Thanks for your time and effort.
If you start with the time in seconds:
display = String.format("%d:%02d", seconds / 60, seconds % 60);
If you don't want the minutes if they are 0:
if (seconds < 60)
display = String.format("%02d", seconds);
else
display = String.format("%d:%02d", seconds / 60, seconds % 60);
You are just going to have to make a function that creates a string for you. Stash this somewhere reachable.
public String NumToStr(long i){
if (i < 10 ) {
return ("0" + Long.toString(i));
}
return Long.toString(i);
}
this will take any number that is less than 10 and give you a string with a "0" infront of the number.
i.e. send it a 7 and get "07" then send it a 55 and get "55" because it was not less than 10. Finaly send it the seconds 5 and get "05". Now add the strings together,
Hour + ":" + Minute + ":" + Seconds;
and you will get "07:55:05"
next just put in a
if (seconds > 60) {
seconds = 0
minutes++;
}
if (minutes > 60) {
minutes = 0
hours++;
}
if (hours > 12) {
hours = 0
}
With all respect this is basic stuff.
In response to where should you put all of this? Where ever you like. But you need to redo some of your code.
case MSG_UPDATE_TIMER:
long TimePassed;
TimePassed = Seconds;
if (Minutes > 0) {
TimePassed = TimePassed + (60 * Minutes);
}
if (Hours > 0) {
TimePassed = TimePassed + (60 * 60 * Hours);
}
Seconds = (timer.getElapsedTimeSecs()- TimePassed );
if (Seconds > 60) {
Seconds = 0
Minutes++;
}
if (Minutes > 60) {
Minutes = 0
hours++;
}
String timeSecs = NumToStr(Seconds);
String timeMins = NumToStr(Minutes);
String timeHours = NumToStr(Hours);
String Time = timeHours + ":" + timeMins + ":" + timeSecs;
tvTextView.setText(Time);
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_TIMER,REFRESH_RATE);
break;

Categories