CountDownTimer unstable according to Android verision / Saving Battery


Currently I need my application after 5 minutes to perform an action in my case to close the session, in my emulators and my phone is 10 but in some phones it does not work, I'm not sure if the battery saving could make do not count the time with CountDownTimer or that could make the time not decrease, I need that the time count for more than the screen is blocked or this background currently use

public class MyCountDownTimer extends CountDownTimer {
    Context context = null;
    public MyCountDownTimer(long startTime, long interval,Context context) {
        super(startTime, interval);
        this.context = context;
    public void onTick(long millisUntilFinished) {

    public void onFinish() {

        Intent intent = new Intent(context, Login.class);

        Toast.makeText(context, context.getString(R.string.SessionExpirada),Toast.LENGTH_LONG).show();

Then I have another method that restarts when the iteractual person

public void onUserInteraction(){

So this is good for me in some and in others it just does not work, I could use another component that meets my requirements or I could fix the CountDownTimer so that it always walks even in the background and in battery saving

asked by Bruno Sosa Fast Tag 19.12.2018 в 21:21

1 answer


@Juan is locally, and I use a timer because I just want to measure   times

This answer does not answer how to implement a timer that triggers a session closure, but how to "close" a local session by measuring the elapsed time and comparing against a predefined limit.

The solution is to save a value long with the time returned by System.currentTimeMillis() every time you interact with the app, and compare this value against the previous one to determine if it passed more than the time limit.

The comparison is achieved by making the difference horaInteraccionActual - horaUltimaInteracción . The result of the difference are milliseconds so to take it to minutes you have to divide by 60000.

To preserve the value of the last interaction we can persist in SharedPreferences . This variable can be read in onResume() and saved in onPause() .

The solution is simple compared to alternatives that involve the use of a service with CountdownTimer, or using AlarmManager. And from the practical point of view what is obtained as a result is very similar: After a certain time the user can not use the app without authenticating .

The difference is that you can not notify the end of session at the end of time (5 minutes in the question), and if there is to do some closing work, it is delayed until the next user interaction. (Although this is debatable since a solution with AlarmManager may be subject to delays as well).

The activity:

public class TimedActivity extends AppCompatActivity {
    private static final String APP_PREFS = "AppPrefs";
    private static final String PRF_UMA_INTERACCION = "ultima_interaccion";
    private static final int TIEMPO_LIMITE_MINS = 5;
    private long ultimaInteraccion = -1;
    private SharedPreferences prefs = null;

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        prefs = getSharedPreferences(APP_PREFS, MODE_PRIVATE);

    protected void onResume() {
        ultimaInteraccion = prefs.getLong(PRF_UMA_INTERACCION, -1);

    protected void onPause() {
        SharedPreferences.Editor editor = prefs.edit();
        editor.putLong(PRF_UMA_INTERACCION, ultimaInteraccion);

    /** Un ejemplo de interaccion **/
    public void unaInteraccion(){

            //Ejecutar interaccion


     * Valida que se esté en la ventana de tiempo permitida para la sesión
     * @return true si se está en la ventana, y false si se está en la ventana o si no
     * hay una última interacción contra que comparar
    private boolean isSesionValida(){
        boolean rtn;
        if(ultimaInteraccion == -1){
            rtn = false;
        }else {
            long horaActual = System.currentTimeMillis();
            int tiempoTranscurridoMins = (int) ((horaActual - ultimaInteraccion) / 60000);
            rtn = tiempoTranscurridoMins <= TIEMPO_LIMITE_MINS;
        return rtn;

     * Método de conveniencia para llamar cuando se quiere acutalizar la hora de la
     * última interacción. Presumiblemente, después de procesar la interacción actual.
    private void interaccionConcretada(){
        ultimaInteraccion = System.currentTimeMillis();

    private void cerrarSesion(){
        // Si el cierre de sesión requiere hacer algo más se puede hacer acá

    private void pedirLogin(){
        boolean autenticado = false;

        // Pedir autenticación para abrir nuevamente una sesion.

        autenticado = <resultado de la autenticación>; // true si se autentica al usuario y false si no se autentica
            ...; //Ir a pantalla principal por ejemplo
answered by 26.12.2018 / 17:15