Saltar al contenido

Android: ¿Cómo pausar y reanudar un temporizador de cuenta atrás?

Por fin después de mucho batallar hemos dado con el arreglo de este enigma que agunos usuarios de nuestro espacio han tenido. Si tienes algo más que compartir no dejes de dejar tu información.

Solución:

/*
 * Copyright (C) 2010 Andrew Gainer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Adapted from Android's CountDownTimer class

package com.cycleindex.multitimer;

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

/**
 * Schedule a countdown until a time in the future, with
 * regular notifications on intervals along the way.
 *
  * The calls to @link #onTick(long) are synchronized to this object so that
 * one call to @link #onTick(long) won't ever occur before the previous
 * callback is complete.  This is only relevant when the implementation of
 * @link #onTick(long) takes an amount of time to execute that is significant
 * compared to the countdown interval.
 */
public abstract class CountDownTimerWithPause 

    /**
     * Millis since boot when alarm should stop.
     */
  private long mStopTimeInFuture;

  /**
   * Real time remaining until timer completes
   */
    private long mMillisInFuture;

    /**
     * Total time on timer at start
     */
    private final long mTotalCountdown;

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

    /**
     * The time remaining on the timer when it was paused, if it is currently paused; 0 otherwise.
     */
    private long mPauseTimeRemaining;

    /**
     * True if timer was started running, false if not.
     */
    private boolean mRunAtStart;

    /**
     * @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 in millis at which to execute
     *   @link #onTick(millisUntilFinished) callbacks
     * @param runAtStart True if timer should start running, false if not
     */
    public CountDownTimerWithPause(long millisOnTimer, long countDownInterval, boolean runAtStart) 
        mMillisInFuture = millisOnTimer;
        mTotalCountdown = mMillisInFuture;
        mCountdownInterval = countDownInterval;
        mRunAtStart = runAtStart;
    

    /**
     * Cancel the countdown and clears all remaining messages
     */
    public final void cancel() 
        mHandler.removeMessages(MSG);
    

    /**
     * Create the timer object.
     */
    public synchronized final CountDownTimerWithPause create() 
        if (mMillisInFuture <= 0) 
            onFinish();
         else 
          mPauseTimeRemaining = mMillisInFuture;
        

        if (mRunAtStart) 
          resume();
        

        return this;
    

    /**
     * Pauses the counter.
     */
  public void pause () 
    if (isRunning()) 
      mPauseTimeRemaining = timeLeft();
      cancel();
    
  

  /**
   * Resumes the counter.
   */
  public void resume () 
    if (isPaused()) 
      mMillisInFuture = mPauseTimeRemaining;
      mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
          mHandler.sendMessage(mHandler.obtainMessage(MSG));
      mPauseTimeRemaining = 0;
    
  

  /**
   * Tests whether the timer is paused.
   * @return true if the timer is currently paused, false otherwise.
   */
  public boolean isPaused () 
    return (mPauseTimeRemaining > 0);
  

  /**
   * Tests whether the timer is running. (Performs logical negation on @link #isPaused())
   * @return true if the timer is currently running, false otherwise.
   */
  public boolean isRunning() 
    return (! isPaused());
  

  /**
   * Returns the number of milliseconds remaining until the timer is finished
   * @return number of milliseconds remaining until the timer is finished
   */
  public long timeLeft() 
    long millisUntilFinished;
    if (isPaused()) 
      millisUntilFinished = mPauseTimeRemaining;
     else 
      millisUntilFinished = mStopTimeInFuture - SystemClock.elapsedRealtime();
      if (millisUntilFinished < 0) millisUntilFinished = 0;
    
    return millisUntilFinished;
  

  /**
   * Returns the number of milliseconds in total that the timer was set to run
   * @return number of milliseconds timer was set to run
   */
  public long totalCountdown() 
    return mTotalCountdown;
  

  /**
   * Returns the number of milliseconds that have elapsed on the timer.
   * @return the number of milliseconds that have elapsed on the timer.
   */
  public long timePassed() 
    return mTotalCountdown - timeLeft();
  

  /**
   * Returns true if the timer has been started, false otherwise.
   * @return true if the timer has been started, false otherwise.
   */
  public boolean hasBeenStarted() 
    return (mPauseTimeRemaining <= mMillisInFuture);
  

    /**
     * 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 (CountDownTimerWithPause.this) 
                long millisLeft = timeLeft();

                if (millisLeft <= 0) 
                    cancel();
                  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's onTick taking time to execute
                    long delay = mCountdownInterval - (SystemClock.elapsedRealtime() - lastTickStart);

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

                    sendMessageDelayed(obtainMessage(MSG), delay);
                
            
        
    ;

Fuente: This Gist.

Una forma agradable y sencilla de crear una pausa / reanudar para su CountDownTimer es crear un método separado para su temporizador comienzo, pausa y reanudar como sigue:

public void timerStart(long timeLengthMilli) {
        timer = new CountDownTimer(timeLengthMilli, 1000) 

            @Override
            public void onTick(long milliTillFinish) 
                milliLeft=milliTillFinish;
                min = (milliTillFinish/(1000*60));
                sec = ((milliTillFinish/1000)-min*60);
                clock.setText(Long.toString(min)+":"+Long.toString(sec));
                Log.i("Tick", "Tock");
            
         
         timer.start();

El timerStart tiene un parámetro largo ya que será reutilizado por el reanudar() método a continuación. Recuerde almacenar su milliTillFinished (arriba como miliLeft) para que pueda enviarlo en su reanudar() método. Pausar y reanudar los métodos siguientes, respectivamente:

public void timerPause() 
        timer.cancel();
    

    private void timerResume() 
        Log.i("min", Long.toString(min));
        Log.i("Sec", Long.toString(sec));
        timerStart(milliLeft);
    

Aquí está el código para el botón FYI:

startPause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(startPause.getText().equals("Start"))
                    Log.i("Started", startPause.getText().toString());
                    startPause.setText("Pause");
                    timerStart(15*1000);
                 else if (startPause.getText().equals("Pause"))
                    Log.i("Paused", startPause.getText().toString());
                    startPause.setText("Resume");
                    timerPause();
                 else if (startPause.getText().equals("Resume"))
                    startPause.setText("Pause");
                    timerResume();
                

Bueno, no hay API para pausarlo o reanudarlo. Lo que debes hacer es cancel() el temporizador y almacenar el tiempo restante en una variable. Cuando vuelva a presionar el botón de reanudar, reinicie el temporizador con el valor de la variable.


Sabe que los cronómetros pueden ser de su interés.

Valoraciones y reseñas

Al final de todo puedes encontrar las interpretaciones de otros administradores, tú también tienes la habilidad mostrar el tuyo si te gusta.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *