Search code examples
androidandroid-asynctaskandroid-animationcountdowntimerbackground-task

Implementing a countdown timer overlaying the activity


I have an activity that is evaluating the person singing in real-time against a reference track. What I want is that when the person clicks on the practice button, there is a countdown for 5 seconds over the screen with all the components on the screen deactivated. I also want to show the countdown on the screen. The idea is to have a transparent grey overlay on top of my Activity view and show the countdown on that. I am thinking of implementing the logic with AsyncTask and CountDownTimer in the Android-SDK. What can be the best ways to achieve the visualization for this?


Solution

  • I was finally able to achieve this without using a CountDownTimer. For this purpose I created a class extending the AsyncTask as follows:

        public class CountdownTask extends AsyncTask<Integer, Integer, Integer> {
    
        private ICountdownView mCountdownView;
    
        private static final String TAG = "CountdownTask";
    
        public CountdownTask(ICountdownView countdownView) {
            this.mCountdownView = countdownView;
        }
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // Code to set up the timer ...
            mCountdownView.initCountdownView();
    
        }
    
        @Override
        protected Integer doInBackground(Integer... params) {
            // setting the default number of steps ..
            int countdownSteps = 5;
            // reading the number of steps if mentioned in the parameters
            if (params.length >= 1 && params[0] != null) {
                countdownSteps = params[0];
            }
    
            // setting the default step duration in milliseconds ..
            int stepDur = 1000;
            // reading the step duration if mentioned in the parameters
            if (params.length >= 2 && params[1] != null) {
                stepDur = params[1];
            }
    
            for (int i = 0; i < countdownSteps; i++) {
                publishProgress(countdownSteps - i);
                sleep(stepDur);
            }
            return null;
        }
    
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            mCountdownView.updateCountdownView(values[0]);
        }
    
        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);
            mCountdownView.destroyCountDownView();
        }
    
        private void sleep(int mDelay) {
            try {
                Thread.sleep(mDelay);
            } catch (InterruptedException e) {
                Log.e(TAG, e.toString());
            }
        }
    }
    

    For updating to UI, I have created an interface ICountdownView. Whichever activity has want a countdown needs to implement this interface and then initialize CountdownTask using new CountdownTask(this), where this refers to the reference of the activity class. The interface ICountdownView is as follows:

        public interface ICountdownView {
    
        void initCountdownView();
    
        void updateCountdownView(int timeLeft);
    
        void destroyCountDownView();
    }
    

    In your activity, you implement all these methods by whatever animation you want. In my case, on initCountdownView(), I initialize a dialog with transparent background and no header. On each updateCountdownView(int timeLeft), I show the time left on the dialog and animate it. On destroyCountDownView(), I dismiss() the dialog and proceed with whatever I need to do the next. Hope this helps!

    PS: You can initiate the CountdownTask with the number of steps and the duration of each step mentioned in milliseconds like:

    mCountdownTask.execute(5, 1000);
    

    This above statement makes the countdown to execute in 5 steps with each step being 1000 milliseconds (1 second) long. This is also the default behavior of the CountdownTask in case the user does not supply with any arguments.