Question

I have an animation in my Android app that flashes a TextView different colors. I've used a TimerTask, Timer, and Runnable method to implement this. What I need to do is stop the thread when a user leaves the app during this animation in onPause(), and resume the thread when the user returns to the app in onResume(). The following is the code I've implemented, but it's not working (the onPause(), and onResume() pieces), and I don't understand why. I've read a few other posts on similar matters, but they haven't helped me figure out what to do in my situation. I've read that TimerTasks are outdated, and I should probably use an ExecutorService method; it is unclear to me as how to implement this function.

   ...timerStep5 = new TimerTask() {

        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                if (b5) {
                    cashButton2SignalText.setBackgroundColor(Color.RED);
                    cashButton2SignalText.setTextColor(Color.WHITE);
                    b5=false;
                } else {
                    cashButton2SignalText.setBackgroundColor(Color.WHITE);
                    cashButton2SignalText.setTextColor(Color.RED);
                    b5=true;
                }
                }
            });
        }
};

timer5.schedule(timerStep5,250,250);

}

public void onPause(){

    super.onPause();

    timerStep5.cancel();

}

public void onResume(){

    super.onResume();

    timerStep5.run();

}
Was it helpful?

Solution

After a TimerTask is canceled, it cannot run again, you have to create a new instance.

Read details here:

https://stackoverflow.com/a/2098678/727768

ScheduledThreadPoolExecutor is recommended for newer code, it handles the cases like exceptions and task taking longer time than the scheduled interval.

But for your task, TimerTask should be enough.

OTHER TIPS

Here's how I did it. Add pauseTimer boolean where ever the pause takes place (button listener perhaps) and don't count timer if true.

private void timer (){
    Timer timer = new Timer();
    tv_timer = (TextView) findViewById(R.id.tv_locationTimer);
    countTimer = 0;
    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    String s_time = String.format("%02d:%02d:%02d",
                            countTimer / 3600,
                            (countTimer % 3600) / 60,
                            countTimer % 60);
                    tv_timer.setText(s_time);
                    if (!pauseTimer) countTimer++;
                }
            });
        }
    }, 1000, 1000);
}

For Kotlin user, checkout this

How to use:

// Init timer
lateinit var timerExt: CountDownTimerExt

timerExt = object : CountDownTimerExt(TIMER_DURATION, TIMER_INTERVAL) {
    override fun onTimerTick(millisUntilFinished: Long) {
        Log.d("MainActivity", "onTimerTick $millisUntilFinished")
    }

    override fun onTimerFinish() {
        Log.d("MainActivity", "onTimerFinish")
    }

}

// Start/Resume timer
timerExt.start()

// Pause timer
timerExt.pause()

// Restart timer
timerExt.restart()
Timer timer1;
private boolean timerStartFlag = false;
private boolean hiddenVisibleFrg = false;
int timerSize = 0;
int videoTime = 0;


@Override
public void onPause() {
    super.onPause();

    Log.e("keshav", "onPause timer1 " +timer1);
    if (timerSize >0 &&hiddenVisibleFrg){
        timerStartFlag =true;
    }

    if (timer1 != null) {
        this.timer1.cancel();
    }

}

@Override
public void onResume() {
    super.onResume();

    if (timerSize >0 && timerStartFlag && hiddenVisibleFrg) {
        callTimerTask(timerSize);
        timerStartFlag = false;
    }
}

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);

    if (!hidden) {
        Log.e("keshav", "HomeFragment  visible ");

        if (timerSize >0 && timerStartFlag) {
            callTimerTask(timerSize);
            timerStartFlag=false;
        }

        hiddenVisibleFrg=true;

    } else {
        Log.e("keshav", "HomeFragment in visible " +timer1);
        if (timer1 != null) {
            this.timer1.cancel();
        }
        if (timerSize >0){
            timerStartFlag =true;
        }
        hiddenVisibleFrg=false;
    }
}


private void callTimerTask(int size) {
    // TODO Timer for auto sliding
    printLog("callTimerTask size " + size);
    timer1 = new Timer();
    timer1.schedule(new TimerTask() {
        @Override
        public void run() {
            if (getActivity() != null) {
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (getActivity() == null) {
                            return;
                        }
                        if (count1 < size - 1) {
                            //TODO ADD ME kk
                            count1++;
                        } else {
                            count1 = 0;
                        }
                        if (intro_images != null) {
                            intro_images.setCurrentItem(count1);
                        }
                        videoTime++;
                        Log.e("KeshavTimer", "callTimerTask videoTime " + videoTime);
                    }
                });
            } else {
                printLog("callTimerTask getActivity is null ");
            }
        }
    }, 1000, 1000);
    // TODO  1000, 3000;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top