Search code examples
javaandroidoopmethodscountdowntimer

Android app to play mp3 file in specific time with countdown timer


I was trying to create an android app that should get time in minutes from a seek bar then it should begin to play a sound file until the countdown timer ends.

Things are mostly fine with the countdown timer BUT my question is how should I call some methods of the countdown timer instance when a button is pressed.

In the code below, I want to call onFinish() whenever the stop button pressed.

Here is my code:

public class MainActivity extends AppCompatActivity {

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

        SeekBar sb = (SeekBar) findViewById(R.id.seekBar);
        Button bt_stop = (Button) findViewById(R.id.btn1);
        final TextView tv = (TextView)findViewById(R.id.textView);



        sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                int millisec_time = (i*60)/1000;

                new CountDownTimer(millisec_time, 1000) {

                    public void onTick(long millisUntilFinished) {
                        tv.setText("seconds remaining: " + millisUntilFinished / 1000);
                    }

                    public void onFinish() {
                        tv.setText("done!");
                    }
                }.start();


            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
//                Toast.makeText(getApplicationContext(),"GOT",Toast.LENGTH_LONG).show();
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
//                Toast.makeText(getApplicationContext(),"OFF",Toast.LENGTH_LONG).show();
            }
        });



        bt_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });



    }
}

Solution

  • First, I'd recommend you only start your CountdownTimer in onStopTrackingTouch - reason being that currently you're creating a brand new timer every time the progress changes on your seekbar (which could be happening a lot).

    Secondly, you'll need to retain a reference to your timer in order to cancel it. So:

    public class MainActivity extends AppCompatActivity {
    
        private CountdownTimer timer = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            final SeekBar sb = (SeekBar) findViewById(R.id.seekBar);
            sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int i, boolean b) {}
    
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {}
    
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                    restartTimer(seekBar);
                }
            }
    
        final Button bt_stop = (Button) findViewById(R.id.btn1);
        bt_stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(timer != null) {
                    timer.cancel();
                }
            }
        });
    
    
        }    
    
        private void restartTimer(SeekBar sb) {
            if(timer!=null) {
                timer.cancel();
            }
            final long millis = TimeUnit.SECONDS.toMillis(sb.getProgress());
            final long interval =  TimeUnit.SECONDS.toMillis(1);
            timer = new CountdownTimer(millis, interval) {
                @Override
                public void onTick(long millisUntilFinished) {
                    tv.setText(String.format("Seconds Remaining: %d", TimeUnit.MILLIS.toSeconds(millisUntilFinished));
                }
    
                @Override
                public void onFinish() {
                    tv.setText("done!");
                }
            }
            timer.start();
        }
    
    }