I have a basic Timer in my app:
TextView timerTextView = (TextView) findViewById(R.id.timer);
long startTime = 0;
Handler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000) * 1;
int minutes = seconds / 60;
seconds = seconds % 60;
timerTextView.setText(String.format("%02d:%02d", minutes, seconds));
timerHandler.postDelayed(this, 500);
if (minutes == 45 && seconds == 0) {
addHeader("2nd Half");
}
}
};
addHeader() method:
private void addHeader(String header) {
TableLayout table = (TableLayout) findViewById(R.id.myTable);
TableRow tr = new TableRow(this);
tr.setLayoutParams(...);
TextView textView = new TextView(this);
textView.setLayoutParams(..);
textView.setText(header);
// more code
tr.addView(textView);
table.addView(tr);
}
onCreate():
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startTimer();
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
}
When my timer reaches 45:00 a new row is added to my TableLayout multiple times. I've created an alternative solution but I'd like to know what I'm missing.
if (!isAdded) {
addHeader("2nd Half");
isAdded = true;
}
A good way to check what is going on is to log every time the Handler is run and every time addHeader fires
e.g:
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000) * 1;
int minutes = seconds / 60;
seconds = seconds % 60;
millis = millis % 1000;
timerTextView.setText(String.format("%02d:%02d", minutes, seconds));
Log.d("MainActivity", String.format(Locale.ENGLISH,"Checking time: %02d:%02d:%03d" , minutes, seconds, millis));
timerHandler.postDelayed(this, 500);
if (minutes == 45 && seconds == 0) {
Log.d("MainActivity", String.format(Locale.ENGLISH,"2nd Half: %02d:%02d:%03d" , minutes, seconds, millis));
addHeader("2nd Half");
}
}
Doing this you will see that addHeader is called twice. This is because every 500ms your Handler is running, checking the difference between the current time and start time, in minutes and seconds (ignoring ms). To fix the issue try changing
timerHandler.postDelayed(this, 500);
to
timerHandler.postDelayed(this, 1000);
Related
Hi I am making countdown timer. And when I put value of minutes less than one minute everything works correctly. But when I put value for example 1:05 min and click start I see counting down from 1:44. And this problem always appears when I put value bigger than 1 minute
//rundowy czasomierz {
mCountDownTimer = new CountDownTimer(millisInput, 1000) {
#Override
public void onTick(long millisUntilFinished) {
mTimeLeftInMillis = millisUntilFinished;
updateCountDownText();
tv4.setText((round_count[0]+1)+"/"+finalNum_rounds);
}
#Override
public void onFinish() {
round_count[0]++;
if (round_count[0]<finalNum_rounds){
Handler handler=new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
start();
}
}, przerwasinput);
}
MediaPlayer ring = MediaPlayer.create(Main6Activity.this, R.raw.ring1);
ring.start();
tv3.setText("Przerwa");
if (!tv1.equals("00:00")) {
tv1.setText("Koniec");
}
private void updateCountDownText(){
int hours = (int) (mTimeLeftInMillis / 1000) / 3600;
int minutes = (int) ((mTimeLeftInMillis / 1000) % 3600) / 60;
int seconds = (int) (mTimeLeftInMillis / 1000) % 60;
String timeLeftFormatted;
timeLeftFormatted = String.format(Locale.getDefault(),
"%02d:%02d", minutes, seconds);
tv1.setText(timeLeftFormatted);
}
My best guess is that your program interprets an input of 1:05 as 105 seconds. This is equal to 1 minute and 45 seconds, so your timer would begin counting down from 1:45.
I don't see where in your code you process input, so I don't know exactly what is causing this.
I have one countdown timer in my activity.
In which I have converted Mins into Millisecond.
Based on that Millisecond, I have managed to counter HH: mm: ss using CountDownTimer.
So, I want a difference between main time and remaining time.
For example, My main time is 00:10:00 and when I stop counter suppose my remaining time is 00:07:30. means I spend 2:30 seconds
An expected result I want is 150seconds.
Example Code:
public class MainActivity extends AppCompatActivity {
int duration;
TextView textView;
ProgressBar progressbar;
Button btn_stop, btn_resume;
CountDownTimer counter;
int i = 1;
int remainingDuration;
int countDownInterval = 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.tvSampleText);
progressbar = (ProgressBar) findViewById(R.id.progressbar);
btn_stop = (Button) findViewById(R.id.btn_stop);
btn_resume = (Button) findViewById(R.id.btn_resume);
// duration=81200000; //6 hours
duration = (int) TimeUnit.MINUTES.toMillis(1);
counter = new MyCount(duration, countDownInterval);
counter.start();
btn_stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
counter.cancel();
}
});
btn_resume.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
counter = new MyCount(remainingDuration, countDownInterval);
counter.start();
}
});
}
public class MyCount extends CountDownTimer {
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
textView.setText("00:00:00");
}
#Override
public void onTick(long millisUntilFinished) {
i++;
long secondsInMilli = 1000;
long minutesInMilli = secondsInMilli * 60;
long hoursInMilli = minutesInMilli * 60;
long elapsedHours = millisUntilFinished / hoursInMilli;
millisUntilFinished = millisUntilFinished % hoursInMilli;
long elapsedMinutes = millisUntilFinished / minutesInMilli;
millisUntilFinished = millisUntilFinished % minutesInMilli;
long elapsedSeconds = millisUntilFinished / secondsInMilli;
String yy = String.format("%02d:%02d:%02d", elapsedHours, elapsedMinutes, elapsedSeconds);
textView.setText(yy);
progressbar.setProgress((int) i * 100 / (duration / (int) secondsInMilli));
remainingDuration = (int) millisUntilFinished;
}
}
}
First convert the minutes duration into seconds
long secs = minutes * 60; 10 * 60 = 600
and inside on tick, you get the remaining time in milliseconds so keep the value as global reference and convert it into seconds as
long mMillisUntilFinished;
void onTick (long millisUntilFinished){
// mMillisUntilFinished = 450000
mMillisUntilFinished = millisUntilFinished;
}
then when you press stop then get the renaming time difference as
long diffSeconds = secs - (mMillisUntilFinished / 1000)
// 600 - (450000 /1000)
// 600 - 450
// 150
update: As suggested, calculate the seconds for both duration and left time then subtract them to get the result.
Use long instead of int casting
#Override
public void onTick(long millisUntilFinished) {
i++;
long secondsInMilli = 1000;
long minutesInMilli = secondsInMilli * 60;
long hoursInMilli = minutesInMilli * 60;
long tempMili = millisUntilFinished;
long elapsedHours = tempMili / hoursInMilli;
tempMili = tempMili % hoursInMilli;
long elapsedMinutes = tempMili / minutesInMilli;
tempMili = tempMili % minutesInMilli;
long elapsedSeconds = tempMili / secondsInMilli;
String yy = String.format("%02d:%02d:%02d", elapsedHours, elapsedMinutes, elapsedSeconds);
textView.setText(yy);
progressbar.setProgress((int) i * 100 / (duration / (int) secondsInMilli));
remainingDuration = (duration/ 1000) - (millisUntilFinished/1000);
}
Here is what I have so far
long startTime = 0;
TextView timerTextView;
final Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) millis / 1000;
int minutes = (int) seconds / 60;
seconds %= 60;
int min = 40000;
int max = 49999;
long randomTime = (long) (Math.random()*(min-max) + max);
timerTextView.setText(minutes + ":" + seconds);
timerHandler.postDelayed(this, 500);
}
};
I want to know how I can use the randomTime variable to trigger my TextView to change to say Time Is Up. I found a way to create a scheduled task using the following:
timerHandler.postAtTime(Runnable r, randomTime);
The only problem is I don't know what Runnable I should use to cause the TextView to change.
First of all put the randomTime outside of the thread,
int min = 40000;
int max = 49999;
long randomTime = (long) (Math.random()*(min-max) + max);
Create a simple handler that'll run after the time specified by randomTime variable,
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// handler has reached the time
// now update the TextView using a runOnUiThread
runOnUiThread(new Runnable() {
public void run() {
// Update UI elements
// get the current time now
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) millis / 1000;
int minutes = (int) seconds / 60;
seconds %= 60;
//finally update the TextView
timerTextView.setText(minutes + ":" + seconds);
}
});
}
}, randomTime);
I have a count up timer in one of my activities and I want to show that timer with elapsed time in my 2nd activity. I tried to Use Fragments for this but the timer keeps restaring on the launch of 2nd activity.
My timer code is:
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
private Runnable updateTimerThread = new Runnable() {
public void run() {
timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
updatedTime = timeSwapBuff + timeInMilliseconds;
int secs = (int) (updatedTime / 1000);
int mins = secs / 60;
secs = secs % 60;
int milliseconds = (int) (updatedTime % 1000);
/* Timer.setText("" + mins + ":"
+ String.format("%02d", secs) + ":"
+ String.format("%03d", milliseconds));*/
customHandler.postDelayed(this, 0);
}
};
Pass the startTime from the first activity to the second in the Intent. In the second activity, don't set startTime to SystemClock.uptimeMillis() but instead read it from the extras in the Intent sent from the first activity.
I have looked everywhere to fix my problem but i just cant seem to get
it going.
How do i make seekbar automatically slide with song play ?
this is what i have so far.
ArrayList<String> arrlist = new ArrayList<String>(20);
private Handler seekHandler = new Handler();
ImageButton next, playPause, previous;
SeekBar seekBar;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
getSupportActionBar().hide();
getInit();
}
public void getInit() {
songCurrentDurationLabel = (TextView) findViewById(R.id.startTime);
songTotalDurationLabel = (TextView) findViewById(R.id.endTime);
mediaPlayer = new MediaPlayer();
mediaPlayer = MediaPlayer.create(this, R.raw.firstsong);
seekBar = (SeekBar) findViewById(R.id.seekBar1);
seekBar.setMax(mediaPlayer.getDuration());
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// remove message Handler from updating progress bar
seekHandler.removeCallbacks(mUpdateTimeTask);
int totalDuration = mediaPlayer.getDuration();
int currentPosition = progressToTimer(seekBar.getProgress(), totalDuration);
// forward or backward to certain seconds
mediaPlayer.seekTo(currentPosition);
// update timer progress again
updateProgressBar();
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// remove message Handler from updating progress bar
seekHandler.removeCallbacks(mUpdateTimeTask);
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mediaPlayer != null && fromUser) {
mediaPlayer.seekTo(progress);
// mediaPlayer.seekTo(progress * 1000);
}
}
});
spinner = ((Spinner) findViewById(R.id.spinner1));
spinner.setAdapter(songAdapter);
previous = ((ImageButton) findViewById(R.id.previous));
playPause = ((ImageButton) findViewById(R.id.play));
next = ((ImageButton) findViewById(R.id.next));
spinner.setOnItemSelectedListener(this);
previous.setOnClickListener(this);
playPause.setOnClickListener(this);
next.setOnClickListener(this);
totalDuration = mediaPlayer.getDuration();
currentDuration = mediaPlayer.getCurrentPosition() / 1000;
// Displaying Total Duration time
songTotalDurationLabel.setText("" + milliSecondsToTimer(totalDuration));
// Displaying time completed playing
songCurrentDurationLabel.setText("" + milliSecondsToTimer(currentDuration));
}
public void updateProgressBar() {
seekHandler.postDelayed(mUpdateTimeTask, 100);
}
private Runnable mUpdateTimeTask = new Runnable() {
#Override
public void run() {
long totalDuration = mediaPlayer.getDuration();
long currentDuration = mediaPlayer.getCurrentPosition() / 1000;
int progress = (int) getProgressPercentage(currentDuration, totalDuration);
// Updating progress bar
seekBar.setProgress(progress);
// Running this thread after 100 milliseconds
seekHandler.postDelayed(this, 100);
}
};
public int progressToTimer(int progress, int totalDuration) {
int currentDuration = 0;
totalDuration = (int) (totalDuration / 1000);
currentDuration = (int) ((((double) progress) / 100) * totalDuration);
// return current duration in milliseconds
return currentDuration * 1000;
}
public int getProgressPercentage(long currentDuration1, long totalDuration1) {
Double percentage = (double) 0;
long currentSeconds = (int) (currentDuration1 / 1000);
long totalSeconds = (int) (totalDuration1 / 1000);
// calculating percentage
percentage = (((double) currentSeconds) / totalSeconds) * 100;
// return percentage
return percentage.intValue();
}
public String milliSecondsToTimer(long milliseconds) {
String finalTimerString = "";
String secondsString = "";
// Convert total duration into time
int hours = (int) (milliseconds / (1000 * 60 * 60));
int minutes = (int) (milliseconds % (1000 * 60 * 60)) / (1000 * 60);
int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60) / 1000);
// Add hours if there
if (hours > 0) {
finalTimerString = hours + ":";
}
// Prepending 0 to seconds if it is one digit
if (seconds < 10) {
secondsString = "0" + seconds;
} else {
secondsString = "" + seconds;
}
finalTimerString = finalTimerString + minutes + ":" + secondsString;
// return timer string
return finalTimerString;
}
I didnt include the song list and all the other stuff as i dont see
why it would be necesary to put here. But anyways, when i do what i
have here i dont get no error or anything, the seekbar just doesnt
automatically move and when i try to move it manually to a position it
goes right back to 0.
U set seekBar.setMax(mediaPlayer.getDuration()); where duration ~ 7 digits value.
After that u count percents ~ 2 digits.
U need set seekBar.setMax(100) or dont count percents and set progress as is.