4

I have a countdown timer that i want to implement on finish method or some kind of code so that when the timer stops, the text views change to Time's up and another method is initiated (in the activity). To clarify, the timer is given a starting number that counts down from, to zero in format of xx:xx.

The class of the timer :

public class countdown_timer {
private  long pls;
private long millisInFuture;
private long countDownInterval;
private boolean status;
public countdown_timer(long pMillisInFuture, long pCountDownInterval) {
    this.millisInFuture = pMillisInFuture;
    this.countDownInterval = pCountDownInterval;
    this.pls = pMillisInFuture;

    status = false;
    Initialize();
}

public void Stop() {
    status = false;
}
public  void Reset() {
    millisInFuture = pls;
}

public long getCurrentTime() {
    return millisInFuture;
}

public void Start() {
    status = true;
}
public void Initialize()
{
    final Handler handler = new Handler();
    Log.v("status", "starting");
    final Runnable counter = new Runnable(){

        public void run(){
            long sec = millisInFuture/1000;
            if(status) {
                if(millisInFuture <= 0) {
                    Log.v("status", "done");
                } else {
                    Log.v("status", Long.toString(sec) + " seconds remain");
                    millisInFuture -= countDownInterval;
                    handler.postDelayed(this, countDownInterval);
                }
            } else {
                Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
                handler.postDelayed(this, countDownInterval);
            }
        }
    };

    handler.postDelayed(counter, countDownInterval);
}

The activty that the timer is used:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_card_game_2);
    //...find views
    mycounterup = new countdown_timer(startcard, 1000);
    mycounterdown = new countdown_timer(startcard, 1000);
    RefreshTimer();
    mycounterdown.Start();

  public void RefreshTimer()
{
    final Handler handler = new Handler();
    final Runnable counter = new Runnable(){

        public void run(){
            int minutes_up_start = (int) (mycounterup.getCurrentTime() / 1000) / 60;
            int seconds_up_start = (int) (mycounterup.getCurrentTime() / 1000) % 60;
            String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
            card_2_up.setText(time_2_up_start_formatted);

            int minutes_down_start = (int) (mycounterdown.getCurrentTime() / 1000) / 60;
            int seconds_down_start = (int) (mycounterdown.getCurrentTime() / 1000) % 60;
            String card_2_down_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_down_start, seconds_down_start);
            card_2_down.setText(card_2_down_start_formatted);
            handler.postDelayed(this, 100);
        }
    };

    handler.postDelayed(counter, 100);
}

2 Answers2

4

You can use CountDownTimer:

new CountDownTimer(endsIn * 1000, 1000) { 
public void onTick(long millisUntilFinished) { 
           timerTextView.setText(String.valueOf(millisUntilFinished/1000);
 } 
public void onFinish() {
} 
}.start();

OR:

extend CountDownTimer class:

public class countdown_timer extends CountDownTimer {
    TextView textView;
    @Override
    public void onTick(long millisInFuture) {
        long sec = millisInFuture/1000;
            if(millisInFuture <= 0) {
                Log.v("status", "done");

        } else {
            Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
        }
    }

    @Override
    public void onFinish() {
        if(textView != null){
            // change text in your textview
        }
    }



    public countdown_timer(long pMillisInFuture, long pCountDownInterval) {
        super(pMillisInFuture, pCountDownInterval);

    }
    public countdown_timer(TextView textView, long pMillisInFuture, long pCountDownInterval) {
        super(pMillisInFuture, pCountDownInterval);
        this.textView = textView;




    }






}

here is a two constructors, one of them is the same as is in your example and in second one you can pass also TextView object and use it in onFinish() method.

UPDATE 2:

Here is CountDownTimer in the Activity:

public class MainActivity extends AppCompatActivity {

    TextView textView;
    CountDownTimer mycounterdown;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        long startcard = 10000;
        textView = (TextView) findViewById(R.id.test);

        mycounterdown = new CountDownTimer(startcard, 1000) {
            @Override
            public void onTick(long mycounterup) {
                int minutes_up_start = (int) (mycounterup / 1000) / 60;
                int seconds_up_start = (int) (mycounterup / 1000) % 60;
                String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
                textView.setText(time_2_up_start_formatted);
            }

            @Override
            public void onFinish() {
                // call here other methods from activity

                testMethod();
            }
        };
        mycounterdown.start();

    }
    public void testMethod(){
        Toast.makeText(MainActivity.this, "Test Method called", Toast.LENGTH_SHORT).show();
    }

}

UPDATE 3: if last tick is one, not zero change count down interval to 500 instead of 1000:

public class MainActivity extends AppCompatActivity {

    TextView textView;
    CountDownTimer mycounterdown;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        long startcard = 10000;
        textView = (TextView) findViewById(R.id.test);

        mycounterdown = new CountDownTimer(startcard, 500) {
            @Override
            public void onTick(long mycounterup) {
                int minutes_up_start = (int) (mycounterup / 1000) / 60;
                int seconds_up_start = (int) (mycounterup / 1000) % 60;
                String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
                textView.setText(time_2_up_start_formatted);
            }

            @Override
            public void onFinish() {
                // call here other methods from activity

                testMethod();
            }
        };
        mycounterdown.start();

    }
    public void testMethod(){
        Toast.makeText(MainActivity.this, "Test Method called", Toast.LENGTH_SHORT).show();
    }

}

NOTE: take a look at this answer

godot
  • 3,422
  • 6
  • 25
  • 42
  • The problem is that with the conventional countdown timer the are many bugs like skipping the last tick,that's why i created a class for it –  Mar 12 '18 at 09:01
  • what you mean in skipping last tick? – godot Mar 12 '18 at 09:04
  • if you mean last tick when time would be equal to zero then you can just write if(millisUntilFinished/1000!=0){ //do stuff } – godot Mar 12 '18 at 09:06
  • Thanks for the help but i don't want to add a new CountDownTimer, i want to use the one i have in the timer class but with an on finish method –  Mar 12 '18 at 09:10
  • How can i initiate another method when timer stops? –  Mar 12 '18 at 11:37
  • method from Activity? – godot Mar 12 '18 at 11:39
  • Yes a method from the activity –  Mar 12 '18 at 11:40
  • if you want to call activity methods why do you want to use custom count down timer and not this one I described first time ? – godot Mar 12 '18 at 11:46
  • because the custom one is more accurate –  Mar 12 '18 at 11:49
  • what kind of inaccuracy have you faced ? – godot Mar 12 '18 at 11:51
  • the conventional one stops at 00:02 then counts 2 sec in the background and then the times up text is shown instead of showing 00:01 then 00:00 and then time's up –  Mar 12 '18 at 11:55
  • check it out again, I updated my answer. I tried to rewrite your logic without custom count down timer – godot Mar 12 '18 at 12:07
  • Stops at 1 sec instead of 0 –  Mar 12 '18 at 12:47
1

First, extend CountDownTimer in your timer class.

public class countdown_timer extends CountDownTimer {

}

This allows you to implement some methods.

@Override
public void onTick(long l) {

}

@Override
public void onFinish() {

}

Also you must implement constructor that matches super class. You can also add some additional parameters. For example TextView

TextView textView;
public countdown_timer(long millisInFuture, long countDownInterval, TextView txt) {
    super(millisInFuture, countDownInterval);
    textView = txt;
}

The onFinish() is what you want. Also make sure you are using this class as a CountDownTimer. Then you will be able to start your timer. Hope it helps.

Cagri Yalcin
  • 402
  • 4
  • 13