Пауза CountDownTimer в Android, когда активность не впереди

У меня есть активность, которая использует CountDownTimer, который отсчитывает от 10. Как приостановить этот таймер, когда активность больше не находится в фокусе, например, если пользователь получил вызов или что-то еще, а затем возобновить таймер, когда пользователь идет вернуться к активности? Возможно ли это?

Ответы

Ответ 1

Я бы добавил что-то к обработчику onTick, чтобы сохранить ход таймера в вашем классе (количество миллисекунд осталось).

В методе onPause() для отмены вызова активности() на таймере.

В методе onResume() для активности создайте новый таймер с сохраненным количеством миллисекунд слева.

Ответ 2

Вы можете использовать pause(), чтобы приостановить таймер, а затем запустить или возобновить countDownTimer, вызвав start().

/**
 * This class uses the native CountDownTimer to 
 * create a timer which could be paused and then
 * started again from the previous point. You can 
 * provide implementation for onTick() and onFinish()
 * then use it in your projects.
 */
public abstract class CountDownTimerPausable {
    long millisInFuture = 0;
    long countDownInterval = 0;
    long millisRemaining =  0;

    CountDownTimer countDownTimer = null;

    boolean isPaused = true;

    public CountDownTimerPausable(long millisInFuture, long countDownInterval) {
        super();
        this.millisInFuture = millisInFuture;
        this.countDownInterval = countDownInterval;
        this.millisRemaining = this.millisInFuture;
    }
    private void createCountDownTimer(){
        countDownTimer = new CountDownTimer(millisRemaining,countDownInterval) {

            @Override
            public void onTick(long millisUntilFinished) {
                millisRemaining = millisUntilFinished;
                CountDownTimerPausable.this.onTick(millisUntilFinished);

            }

            @Override
            public void onFinish() {
                CountDownTimerPausable.this.onFinish();

            }
        };
    }
    /**
     * 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();
    /**
     * Cancel the countdown.
     */
    public final void cancel(){
        if(countDownTimer!=null){
            countDownTimer.cancel();
        }
        this.millisRemaining = 0;
    }
    /**
     * Start or Resume the countdown. 
     * @return CountDownTimerPausable current instance
     */
    public synchronized final CountDownTimerPausable start(){
        if(isPaused){
            createCountDownTimer();
            countDownTimer.start();
            isPaused = false;
        }
        return this;
    }
    /**
     * Pauses the CountDownTimerPausable, so it could be resumed(start)
     * later from the same point where it was paused.
     */
    public void pause()throws IllegalStateException{
        if(isPaused==false){
            countDownTimer.cancel();
        } else{
            throw new IllegalStateException("CountDownTimerPausable is already in pause state, start counter before pausing it.");
        }
        isPaused = true;
    }
    public boolean isPaused() {
        return isPaused;
    }
}

Ответ 3

Не нужно создавать новый таймер, просто установите значение millisUntilFinished = total. Например,

private CountDownTimer cdTimer;
private long total = 30000;

        ...
        toggleButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view){
                if(toggleButton.isChecked()) {
                    startCountDownTimer();
                }else{
                    cdTimer.cancel();
                }
            }
        });
        ...

    private void startCountDownTimer() {
        cdTimer = new CountDownTimer(total, 1000) {
            public void onTick(long millisUntilFinished) {
                //update total with the remaining time left
                total = millisUntilFinished;
                nTimeLabel.setText("seconds remaining: " +  millisUntilFinished/ 1000);
            }
            public void onFinish() {
                nTimeLabel.setText("done!");
            }
        }.start();
    }

Ответ 4

Это должно быть именно то, что вы ищете. Источник этот Gist.

package alt.android.os;

import android.os.Handler;
import android.os.SystemClock;
import android.os.Message;

public abstract class CountDownTimer {

/**
 * 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;

private long mPauseTime;

private boolean mCancelled = false;

private boolean mPaused = false;

/**
 * @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 CountDownTimer(long millisInFuture, long countDownInterval) {
    mMillisInFuture = millisInFuture;
    mCountdownInterval = countDownInterval;
}

/**
 * Cancel the countdown.
 *
 * Do not call it from inside CountDownTimer threads
 */
public final void cancel() {
    mHandler.removeMessages(MSG);
    mCancelled = true;
}

/**
 * Start the countdown.
 */
public synchronized final CountDownTimer start() {
    if (mMillisInFuture <= 0) {
        onFinish();
        return this;
    }
    mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
    mHandler.sendMessage(mHandler.obtainMessage(MSG));
    mCancelled = false;
    mPaused = false;
    return this;
}

/**
 * Pause the countdown.
 */
public long pause() {
    mPauseTime = mStopTimeInFuture - SystemClock.elapsedRealtime();
    mPaused = true;
    return mPauseTime;
}

/**
 * Resume the countdown.
 */
public long resume() {
    mStopTimeInFuture = mPauseTime + SystemClock.elapsedRealtime();
    mPaused = false;
    mHandler.sendMessage(mHandler.obtainMessage(MSG));
    return mPauseTime;
}

/**
 * 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();


private static final int MSG = 1;


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

    @Override
    public void handleMessage(Message msg) {

        synchronized (CountDownTimer.this) {
            if (!mPaused) {
                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();
                } 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 onTick taking time to execute
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

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

                    if (!mCancelled) {
                        sendMessageDelayed(obtainMessage(MSG), delay);
                    }
                }
            }
        }
    }
};
}

Ответ 5

Вы можете попробовать использовать Hourglass

Hourglass hourglass = new Hourglass(50000, 1000) {
        @Override
        public void onTimerTick(long timeRemaining) {
            // Update UI
            Toast.show(MainActivity.this, String.valueOf(timeRemaining), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onTimerFinish() {
            // Timer finished
            Toast.show(MainActivity.this, "Timer finished", Toast.LENGTH_SHORT).show();


        }
    };

Используйте hourglass.startTimer();, чтобы запустить таймер.

У этого есть вспомогательные методы, которые позволяют приостанавливать и возобновлять таймер.

hourglass.pauseTimer();

и

hourglass.resumeTimer();