That guy
That guy

Reputation: 133

How to start a timer using another timer in Android Studio

I'm a novice in Java (Less than 3 months experience), and for a project I've been working on I need to create a timer. I've done this before, however I do not know how to do one thing.

I want to start a timer when a second timer ends. What I mean by this is that instead of using a start/stop button to start a timer, I want to have a second timer (that starts at 3 seconds) determine when the first timer starts. For example, if the first timer is at 30 seconds, it will start counting down when the second timer finishes counting down from 3-0.

I know there has to be other classes or methods/listeners to do this, but as I've stated earlier, it's my first time ever working with Java (I normally use C++).

Any help/guidance/code on how to achieve this would be awesome. Here is the code I was toying around with to try and achieve this.

Java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button; 
import android.widget.TextView;
import android.os.CountDownTimer;

public class Timer extends AppCompatActivity
{
TextView timer;
TextView timerStart;
Button multi;
int track;
int seconds;
CountDownTimer countDownTimer;
CountDownTimer start;

View.OnClickListener btnListen = new View.OnClickListener(){
    @Override
    public void onClick(View v)
    {
        switch(v.getId())
        {
            case R.id.multi : start();
                break;
        }
    }

};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_timer);
    timer = (TextView) findViewById(R.id.timer);
    timerStart = (TextView) findViewById(R.id.timerStart);
    multi = (Button) findViewById(R.id.multi);
    multi.setOnClickListener(btnListen);

    multi.setText("Start");
}

public void start_timer()
{
    track = 3;
    start = new CountDownTimer(3*1000,1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            timerStart.setText("" + millisUntilFinished / 1000);
        }

        @Override
        public void onFinish() {
            timerStart.setText("Begin");
            track = 0;
        }
    }.start();
    seconds = 30;
    if (timerStart.getText().equals("Begin"))
    {
        start.cancel();
        countDownTimer = new CountDownTimer(30 * 1000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                timer.setText("" + millisUntilFinished / 1000);
            }

            @Override
            public void onFinish() {
                timer.setText("BEEP");
            }
        }.start();
    }
    else
    {
        System.out.println("Nothing");
    }
}
public void start()
{
    start_timer();
    /*seconds = 30;
    if (timerStart.getText().equals("Begin"))
    {
        countDownTimer = new CountDownTimer(seconds * 1000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                timer.setText("" + millisUntilFinished / 1000);
            }

            @Override
            public void onFinish() {
                timer.setText("BEEP");
            }
        }.start();
    }*/

}
}

Again, this is just something I'm toying around with. If there is a different way to do this (Like using a Runnable or Handler), then I'm open to it. My goal is to learn Java.

Upvotes: 0

Views: 1385

Answers (1)

nakano531
nakano531

Reputation: 523

How about this? I modified CountDownTimer to enable to be chained.

 public abstract class ChainedCountDownTimer {

    /**
     * Millis since epoch when alarm should stop.
     */
    private final long mMillisInFuture;

    /**
     * The interval in millis that the user receives callbacks
     */
    private final long mCountdownInterval;

    private long mStopTimeInFuture;

    /**
     * boolean representing if the timer was cancelled
     */
    private boolean mCancelled = false;

    /**
     * First timer in chaining
     */
    private ChainedCountDownTimer first;

    /**
     * Next timer
     */
    private ChainedCountDownTimer next;

    /**
     * @param millisInFuture The number of millis in the future from the call
     *   to {@link #start()} until the countdown is done and {@link #onFinish()}
     *   is called.
     * @param countDownInterval The interval along the way to receive
     *   {@link #onTick(long)} callbacks.
     */
    public ChainedCountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
        first = this;
    }

    /**
     * Cancel the countdown.
     */
    public synchronized final void cancel() {
        first.mCancelled = true;
        mHandler.removeMessages(MSG);
    }

    public void start() {
        first.startInternal();
    }

    /**
     * Start the countdown.
     */
    public synchronized final ChainedCountDownTimer startInternal() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();

            if (next != null) {
                next.startInternal();
            }

            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }


    /**
     * Callback fired on regular interval.
     * @param millisUntilFinished The amount of time until finished.
     */
    public abstract void onTick(long millisUntilFinished);

    /**
     * Callback fired when the time is up.
     */
    public abstract void onFinish();

    public ChainedCountDownTimer setNext(ChainedCountDownTimer next) {
        this.next = next;
        next.first = this.first;

        return this.next;
    }

    private static final int MSG = 1;


    // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (ChainedCountDownTimer.this) {
                if (first.mCancelled) {
                    return;
                }

                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();

                    if (next != null) {
                        next.startInternal();
                    }

                } else if (millisLeft < mCountdownInterval) {
                    // no tick, just delay until done
                    sendMessageDelayed(obtainMessage(MSG), millisLeft);
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
                    while (delay < 0) delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };
}

You can use it like this.

ChainedCountDownTimer timer1 = new ChainedCountDownTimer(3 * 1000, 1000) {
    @Override
    public void onTick(long millisUntilFinished) {
        Log.d(TAG, "timer1 onTick");
    }

    @Override
    public void onFinish() {
        Log.d(TAG, "timer1 onFinish");
    }
};

ChainedCountDownTimer timer2 = new ChainedCountDownTimer(30 * 1000, 1000) {
    @Override
    public void onTick(long millisUntilFinished) {
        Log.d(TAG, "timer2 onTick");
    }

    @Override
    public void onFinish() {
        Log.d(TAG, "timer2 onFinish");
    }
};

timer1.setNext(timer2).start();

Upvotes: 1

Related Questions