I've got an activity that plays some music via a MediaPlayer
. Normally when I want to stop the song, I pass the MediaPlayer to a CountDownTimer
that fades the volume to zero, and then releases the MediaPlayer. This seems to work fine, except that I'm having a problem when my activity pauses, such as after touching the home button.
I'm calling cancel()
on the CountDownTimer in onPause
, but it seems that since the activity is pausing, the CountDownTimer never receives the message before it is destroyed (?), and thus the finish()
of CountDownTimer is not called.
The result of this is that after exiting the application, the music continues to play at whatever volume was last set in the CountDownTimer, but it never finishes. So now I'm stuck out of my application with the MediaPlayer running and no way to stop it (very bad).
Is it normal for a CountDownTimer to not get called onFinish
when the activity is exiting, even if I called cancel?
This is my code:
public void StopSong(boolean fadeout){
musicPlaying = false;
if(_player != null) {
final int fadeTime = 1000;
CountDownTimer timer = new CountDownTimer(fadeTime,50) {
final private MyMusicPlayer mFadePlayer = _player;
@Override
public void onTick(long millisUntilFinished) {
mFadePlayer.setFade((float)millisUntilFinished / (float)fadeTime);
Log.d("tag", "Fade timer " + millisUntilFinished+ "ms remaining.");
}
@Override
public void onFinish() {
mFadePlayer.stop();
mFadePlayer.release();
Log.d("tag", "Fade timer finished, releasing resource.");
}
};
timer.start();
mFadeTimers.add(timer);
Log.d("tag", "Song stopping, starting fade timer.");
_player = null;
}
}
And in onPause:
for(CountDownTimer t : mFadeTimers){
Log.d("tag", "Cancelling fade timer on destroy.");
t.cancel();
}
mFadeTimers.clear();
If everything was working fine, I would see the "cancelling fade timer" log message, followed by "Fade timer finished, releasing", but I never get the onFinish()
logcat message.
I just see this:
tag Song stopping, starting fade timer.
tag Application exiting, destroying all audio resources
tag Cancelling fade timer on destroy.
How can I successfully abort all my countdowntimers on exiting the activity?
Take a look at the source code. You'll see that cancel()
does not call onFinish()
, this is just the way CountDownTimer is designed.
You can call onFinish()
yourself though:
for(CountDownTimer t : mFadeTimers){
Log.d("tag", "Cancelling fade timer on destroy."); // ought to read "in onPause", right?
t.cancel();
t.onFinish();
}
mFadeTimers.clear();