Search code examples
javaandroidcountdowntimer

Problems with .cancel() in Android CountDownTimer


I have problems with the Android CountDownTimer.

I am trying to learn myself some JAVA/Android, and have started on a simple app for my self to use when I brew coffee. I cannot get the .cancel () function for the CountDown Timer to work. I have read several threads on this and other forums.

My Java Code:

package jandidrik.kaffe;

import android.content.Context;
import android.os.CountDownTimer;
import android.os.Vibrator;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.view.View;
import android.widget.Toast;

import java.util.concurrent.TimeUnit;


public class MainActivity extends AppCompatActivity implements OnSeekBarChangeListener {

private SeekBar WaterSeekBar, CoffeeSeekBar, BloomingSeekBar, BrewingSeekBar;
private TextView WaterText, CoffeeText, BloomingText, BrewingText, TimerText;

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

    WaterSeekBar = (SeekBar) findViewById(R.id.WaterSeekBar);
    CoffeeSeekBar = (SeekBar) findViewById(R.id.CoffeeSeekBar);
    BloomingSeekBar = (SeekBar) findViewById(R.id.BloomingSeekBar);
    BrewingSeekBar = (SeekBar) findViewById(R.id.BrewingSeekBar);

    WaterText = (TextView) findViewById(R.id.WaterText);
    CoffeeText = (TextView) findViewById(R.id.CoffeeText);
    BloomingText = (TextView) findViewById(R.id.BloomingText);
    BrewingText = (TextView) findViewById(R.id.BrewingText);
    TimerText = (TextView) findViewById(R.id.Timer);

    WaterSeekBar.setOnSeekBarChangeListener(this);
    CoffeeSeekBar.setOnSeekBarChangeListener(this);
    BloomingSeekBar.setOnSeekBarChangeListener(this);
    BrewingSeekBar.setOnSeekBarChangeListener(this);

    WaterSeekBar.setProgress(1000);
    WaterText.setText(Integer.toString(WaterSeekBar.getProgress()));
    CoffeeSeekBar.setProgress(63);
    CoffeeText.setText(Integer.toString(CoffeeSeekBar.getProgress()));

    Long Minutes = TimeUnit.SECONDS.toMinutes(BrewingSeekBar.getProgress());
    Long Seconds = BrewingSeekBar.getProgress() - TimeUnit.MINUTES.toSeconds(Minutes);
    BrewingText.setText("" + String.format("%01d:%02d", Minutes, Seconds));
}

@Override
public void onProgressChanged(SeekBar Bar, int progress, boolean fromUser) {
    switch (Bar.getId()) {
        case R.id.WaterSeekBar:
            WaterText.setText(Integer.toString(progress));
            break;
        case R.id.CoffeeSeekBar:
            CoffeeText.setText(Integer.toString(progress));
            break;
        case R.id.BloomingSeekBar:
            BloomingText.setText(Integer.toString(progress));
            break;
        case R.id.BrewingSeekBar:
            Long Minutes = TimeUnit.SECONDS.toMinutes(BrewingSeekBar.getProgress());
            Long Seconds = BrewingSeekBar.getProgress() - TimeUnit.MINUTES.toSeconds(Minutes);
            BrewingText.setText("" + String.format("%01d:%02d", Minutes, Seconds));
            break;
    }
}

@Override
public void onStartTrackingTouch(SeekBar Bar) {
}

@Override
public void onStopTrackingTouch(SeekBar Bar) {
}

public void Brew(View V) {

    final Button BrewButton = (Button) V;
    final String ButtonText = BrewButton.getText().toString();

    CountDownTimer Count = new CountDownTimer(BrewingSeekBar.getProgress() * 1000, 1000) {

        @Override
        public void onTick(long millisUntilFinished) {
            Long Minutes = TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished);
            Long Seconds = TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(Minutes);

            TimerText.setText("" + String.format("%01d:%02d", Minutes, Seconds));

            int VibrateTime = BrewingSeekBar.getProgress() - BloomingSeekBar.getProgress();

            if ((TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished)) == VibrateTime) {
                Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                // Vibrate 500ms
                v.vibrate(500);

                Toast.makeText(MainActivity.this, "Blooming is finnished!", Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFinish() {
            TimerText.setText("Finished!");
        }
    };

    if (ButtonText.equals("Start Brewing!")) {
        Count.start();
        BrewButton.setText("Stop Timer!");
    } else {
        Count.cancel();
        BrewButton.setText("Start Brewing!");
    }
}
}

My XML Code:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:keepScreenOn="true">
tools:context="jandidrik.kaffe.MainActivity">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Adjust Amount of water (ml)"
    android:layout_marginBottom="8dp"
    android:layout_marginTop="16dp"
    />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<SeekBar
    android:id="@+id/WaterSeekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="1200"
    android:progress="1000"
    android:layout_weight="2"
    />

<TextView
    android:id="@+id/WaterText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="14"
    android:text="1000"
    android:layout_marginLeft="8dp"
    />

</LinearLayout>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Adjust Amount of coffee (g)"
    android:layout_marginBottom="8dp"
    android:layout_marginTop="8dp"
    />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

<SeekBar
    android:id="@+id/CoffeeSeekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="100"
    android:progress="63"
    android:layout_weight="2"
    />

    <TextView
        android:id="@+id/CoffeeText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="63"
        android:layout_weight="14"
        android:layout_marginLeft="8dp"
        />

</LinearLayout>

<TextView
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:background="@android:color/darker_gray"
    android:layout_marginTop="52dp"
    android:layout_marginBottom="52dp"
    />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Set the blooming time (s)"
    android:layout_marginBottom="8dp"
    />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <SeekBar
        android:id="@+id/BloomingSeekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="60"
        android:progress="30"
        android:layout_weight="2"
        />

    <TextView
        android:id="@+id/BloomingText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="30"
        android:layout_weight="14"
        android:layout_marginLeft="8dp"
        />

</LinearLayout>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Set the total brewing time (m:ss("
    android:layout_marginBottom="8dp"
    android:layout_marginTop="8dp"
    />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <SeekBar
        android:id="@+id/BrewingSeekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="480"
        android:progress="240"
        android:layout_weight="2"
        />

    <TextView
        android:id="@+id/BrewingText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="4 min 0 s"
        android:layout_weight="14"
        android:layout_marginLeft="8dp"
        />

</LinearLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

<Button
    android:id="@+id/BrewButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Start Brewing!"
    android:layout_centerInParent="true"
    android:layout_marginTop="16dp"
    android:layout_marginBottom="16dp"
    android:onClick="Brew"

    />

</RelativeLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

<Chronometer
    android:id="@+id/Timer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:format="%s:%s"
    android:layout_centerInParent="true"
    />
</RelativeLayout>

</LinearLayout>

Solution

  • You are trying to stop wrong instance of CountDownTimer. The simplest way to fix your code is just moving out Count out of method.

    private CountDownTimer currentCount;
    public void Brew(View v) {
        final Button BrewButton = (Button) V;
        final String ButtonText = BrewButton.getText().toString();
    
        if (ButtonText.equals("Stop Timer!") && currentCount != null) {
            currentCount.cancel();
            currentCount = null;
            BrewButton.setText("Start Brewing!");
            return;
        }
    
        currentCount = new CountDownTimer(BrewingSeekBar.getProgress() * 1000, 1000) {
    
            @Override
            public void onTick(long millisUntilFinished) {
                Long Minutes = TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished);
                Long Seconds = TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(Minutes);
    
                TimerText.setText("" + String.format("%01d:%02d", Minutes, Seconds));
    
                int VibrateTime = BrewingSeekBar.getProgress() - BloomingSeekBar.getProgress();
    
                if ((TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished)) == VibrateTime) {
                    Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                    // Vibrate 500ms
                    v.vibrate(500);
    
                    Toast.makeText(MainActivity.this, "Blooming is finnished!", Toast.LENGTH_LONG).show();
                }
            }
    
            @Override
            public void onFinish() {
                TimerText.setText("Finished!");
            }
        };
    
        currentCount.start();
        BrewButton.setText("Stop Timer!");
    }