Android: Timer onTick problem - android

Hi I'm working on one of my project then I encountered this problem, well I don't know if it is a bug or something I just want to share hoping to get some answer to enlighten my day. So here's the problem:
I made a countdown timer for my project which will run for 2 minutes (that will be 120 seconds) 1000 is the interval time (1000ms = 1s) then I set a checker, an integer of 120 (declared globally) which will be diminished by one each time the timer ticks. The integer will be shown on a textView counting down. then will show a message when the integer reaches the onFinish of the timer. That message will give how much time I've spent by deducting the declared integer by 120.
The problem here is that the timer stops before it reaches 1 given that it will not be deducted by the last tick. The hardest part is that sometimes it stops with 4 or even 5 on the remaining time. Can Anyone help me about this one? Thanks in advance!
Here's my code for further understanding:
//declared a timer
int timer = 120;
//starts the timer
gameTimer = new gameTimer(120000, 1000);
gameTimer.start();
private class gameTimer extends CountDownTimer{
public gameTimer(long startTime, long interval)
{
super(startTime, interval);
}
public void onTick(long millisUntilFinished)
{
//on tick deduct timer by 1
timer -= 1;
TextView timer1 = (TextView)findViewById(R.id.textView1);
timer1.setText(""+timer);
}
public void onFinish()
{
//PERFORM END ACTION UPON FINISHING THE GAME
endtime = 120 - timer;
TextView endtime1 = (TextView)findViewById(R.id.textView2);
1.setText(""+endtime);
}
}

First *: this is your class that extended the* CountDownTimer :
public class GameTimer extends CountDownTimer{
private YourActivity context;
private int timer = 120;
private int endtime;
private TextView timer1,endTime1;
public gameTimer(YourActivity context, long startTime, long interval)
{
// passing the context of your activity
this.context = context;
//get the textView to display results
timer1 = (TextView)this.context.findViewById(R.id.textView1);
endTime1 = (TextView)this.context.findViewById(R.id.textView2);
super(startTime, interval);
}
public void onTick(long millisUntilFinished)
{
//on tick deduct timer by 1
timer -= 1;
//override the method runOnUIThread
context.runOnUiThread(new Runnable(){
#override
public void run(){
timer1.setText(""+timer);
}
});
}
public void onFinish()
{
//PERFORM END ACTION UPON FINISHING THE GAME
endtime = 120 - timer;
//override the method runOnUIThread
context.runOnUiThread(new Runnable(){
#override
public void run(){
endTime1.setText(""+endtime);
}
});
}
}
Second : in your activity ( on the method onCreate() , instanciate your GameTimer and start it :
//instanciate the GameTimer and pass the context to it
GameTimer gameTimer = new GameTimer(this, 120000, 1000);
gameTimer.start();

Related

how do i add miliseconds option in this code?

I am learning android. I made this stopwatch app work from my reference book.It only shows Hour:minutes:seconds but I want to add milliseconds right to the seconds.how do I do that.
code::-
public class StopWatchActivity extends AppCompatActivity {
int seconds;
boolean running;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stop_watch);
runTimer();
}
public void startTimer(View view){
running = true;
}
public void stopTimer(View view){
running = false;
}
public void resetTimer(View view){
running = true;
seconds = 0;
}
public void runTimer(){
final TextView textView = (TextView) findViewById(R.id.timer);
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
int hours = seconds / 3600;
int minutes = (seconds % 3600) / 60;
int sec = seconds % 60;
String time = String.format("%d:%02d:%02d", hours,
minutes,sec);
textView.setText(time);
if(running) {
seconds++;
}
handler.postDelayed(this, 1000);
}
});
}
}
The first step would be to change the field seconds to milliSeconds because you want to keep track of that TimeUnit.
When restarting your handler with handler.postDelayed(this, 1000); define 1 millisecond as delay instead of 1000 (= 1 Second) like this handler.postDelayed(this, 1); then you just need to adjust your calculations and you are done :-)
An easier solution would be:
Instead of saving the elapsed seconds in your activity, save the time that the timer started (e.g. startTime)
Then, in your handler's runnable, get the current time and subtract the start time to find the elapsed time.
Pseudocode:
long startTimeNanos
public void runTimer() {
startTime = new Date()
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
long currentTime = System.nanoTime()
long elapsedNanos = currentTime - startTimeNanos
// calculate seconds and millis
// and set the textview text
handler.postDelayed(this, 1000);
}
});
}
This way, you can change the time that the handler fires and it won't affect anything else.

how to continue timer in app when come back from onRestart state

i've created a small app of memory game. in that app i have created a timer that show the time that take the user to finish the game. my problem is that the timer freeze after i go to another page (like home screen) and back to the game- the time remain at the same time it was stopped.....(i khnow it related somehow to onRestarte() method but dont know what to do..) i want that the timer will continue at the same time it has been stopped. (like if the user have an incall in the middle of the game and then want to continue).
package com.example.kineret.memorygame;
public class Game4x4Activity extends AppCompatActivity implements View.OnClickListener{
TextView timerTextView;
long startTime = 0;
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
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game4x4);
timerTextView = (TextView) findViewById(R.id.timerTextView4x4);
}
#Override
public void onPause() {
super.onPause();
timerHandler.removeCallbacks(timerRunnable);
}
#Override
public void onClick(View view) {
if(newGame) {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
newGame = false;
}
// rest of my code...
}
i have edited your code. plz try this
public class Game4x4Activity extends AppCompatActivity implements View.OnClickListener{
// make a new variable
static long elapsedTime = 0;
TextView timerTextView;
long startTime = 0;
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
// change here
long millis = (System.currentTimeMillis() - startTime) + elapsedTime;
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
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game4x4);
timerTextView = (TextView) findViewById(R.id.timerTextView4x4);
}
#Override
public void onPause() {
// change here
elapsedTime = elapsedTime + (System.currentTimeMillis() - startTime);
timerHandler.removeCallbacks(timerRunnable);
super.onPause();
}
#Override
public void onResume() {
super.onResume();
// change here
if(!newGame) {
startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);
}
}
If the user gets a phone call your app will call onPause then if they finish their phone call and play your game your activity will get onResume called.
in onPause save the system time, in onResume get the latest system time. Take these away from each other (in onResume) and you will have the time that the user was not in your app, you can then add this to your timer before you restart it.
You may also have to persist this time with onSaveInstanceState at other points.

how to measure the time taken by activities in android

I am working on quiz type application and I want to calculate the time between some activities. for example, my level starts from activity A and ends at activity H. I want to calculate the time taken by all the activities. Can anyone please help me to count the time taken from the first activity to the ending activity?
Declare the variables
//counter of time since app started, a background task
private long mStartTime = 0L;
private TextView mTimeLabel;
//handler to handle the message to the timer task
private Handler mHandler = new Handler();
Start the timer in onCreate or onStart or your own method (click of button)
if(mStartTime==0L){
mStartTime=SystemClock.uptimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask,100);
}
timer function
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
final long start = mStartTime;
long millis = SystemClock.uptimeMillis() - start;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
mTimeLabel.setText("" + minutes + ":"
+ String.format("%02d", seconds));
mHandler.postDelayed(this, 200);
}
};
when the app is minimized, pause the timer
#Override
protected void onPause() {
mHandler.removeCallbacks(mUpdateTimeTask);
super.onPause();
}
when the app is resumed, resume the timer
#Override
protected void onResume() {
super.onResume();
mHandler.postDelayed(mUpdateTimeTask, 100);
}

How to dispose CountDownTimer

I have main class called "MainActivity" and I'm lanuching it few times in my App.
private static CountDownTimer timer;
private static final long startTime = 15 * 1000;
private static final long interval = 1 * 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timer = new StageCountDownTimer(startTime, interval);
}
private class StageCountDownTimer extends CountDownTimer {
public StageCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
//STARTTING NEW ACTIVITY
}
#Override
public void onTick(long millisUntilFinished) {
}
}
Sometimes user need to close this activity before count down ends, and return to the this activity again. And then new count down is launching but the old one execute the code in onFinish() when previous count down ends. Everything works great when I start this code once. How to cancel/dispose/destroy this timer after exiting from activity? I tried timer.cancel() and nothing happen.
EDIT
I think I solved my problem by setting CountDownTimer timer as a public and in other Activity i'm just using MainActivity.timer.cancel()
You can use:
if (isFinishing()) {
CountDownTimer.cancel();
}
so if the acitvity is finishing, the countdowntimer gets canceled. and next time you open the acitvity, new countdowntimer will be up.
In addition to timer.cancel() (which should work) you can do in your timer's onFinish():
#Override
public void onFinish() {
if(!MainActivity.this.isFinishing()) {
// Start new activity...
}
}
I think I solved my problem by setting CountDownTimer timer as a public and in other Activity i'm just using MainActivity.timer.cancel()

Android - CountDownTimer will not use a variable as the first parameter

I'm trying to pass the countdowntimer a variable and use that variable as the amount of milliseconds to count down. If I simply enter the value the countdown works properly, but if I pass it a long variable it just runs the onFinish function.
Here's the actual code:
public CountDownTimer countDown = new CountDownTimer(respawnTime, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timer =(Integer)(int) millisUntilFinished / 1000;
if(timer < 31)
timerText.setTextColor(Color.parseColor("#FF0000"));
timerText.setText(timer.toString());
}
#Override
public void onFinish() {
timerText.setTextColor(Color.parseColor("#00FF00"));
timerText.setText("UP");
}
};
At this point I have respawnTime set to equal 360000 hoping for a 360 second countdown, but like I said it just immediately runs the onFinish. Simply changing the first parameter to a literal instead of a variable fixes everything but I need to use a variable here. Thanks in advance for the help!
Change
#Override
public void onTick(long millisUntilFinished) {
to
#Override
public void onTick(long respawnTime) {
use the variable you are sending in the constructor in onTick().
Edit
Here is one of mine
private class MyCountDown extends CountDownTimer
{
long duration, interval;
public MyCountDown(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
// TODO Auto-generated constructor stub
duration = millisInFuture;
interval = countDownInterval;
start();
}
#Override
public void onFinish() {
secs = 10;
Intent intent = new Intent(CalibrationTimeoutScreen.this, CalibrationTakeTempScreen.class);
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);
CalibrationTimeoutScreen.this.finish();
}
#Override
public void onTick(long duration) {
cd.setText(String.valueOf(secs));
secs = secs - 1;
}
}
You did not run start(). Simply add .start() after the last '}' or add a new line calling countDown.start().

Categories

Resources