Search code examples
androidandroid-mediaplayeronbackpressed

Mediaplayer crashes the app onBackPressed


Can anybody tell me why the back button crashes the app? It doesn't matter what I change in the code, be it a try/catch, onDestroy, onBackPressed, it crashes every time, but only if I have started the media player once. If I haven't started it from the screen, the back button doesn't crash the app. What am I doing wrong? Thanks

public class Lesson1Grammar extends Activity implements SeekBar.OnSeekBarChangeListener{

private SeekBar seekBar;
private TextView songCurrentDurationLabel;
private TextView songTotalDurationLabel;
MediaPlayer wholeTextPlayer;
private Utilities utils;
final Handler handler = new Handler();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.lesson1grammar);

    final RelativeLayout playerScreen = (RelativeLayout) findViewById(R.id.playerScreen);
    seekBar = (SeekBar) findViewById(R.id.seekBar);
    seekBar.setOnSeekBarChangeListener(this);
    songCurrentDurationLabel = (TextView) findViewById(R.id.songCurrentDurationLabel);
    songTotalDurationLabel = (TextView) findViewById(R.id.songTotalDurationLabel);
    utils = new Utilities();

    final ImageButton btn_player_screen = (ImageButton) findViewById(R.id.btn_player_screen);
    btn_player_screen.setOnClickListener(new View.OnClickListener() {
        //this hides/unhides the part of the layout in which the player is
        @Override
        public void onClick(View arg0) {
            if (playerScreen.isShown()) {
                playerScreen.setVisibility(View.GONE);
            } else {
                playerScreen.setVisibility(View.VISIBLE);
            }
        }
    });

    final Button btn_default_acc_whole = (Button) findViewById(R.id.btn_default_acc_whole);
    btn_default_acc_whole.setOnClickListener(new View.OnClickListener() {
        public void onClick(View arg0) {//problem here is
            if (playerState == PlayerState_ScAcc) {
                stopSentencePlayer();
                setEngAu(R.raw.default_acc_audio);
                wholeTextPlayer.start();
                setPlayerState(PlayerState_DefAcc);
            }else if (playerState == PlayerState_Sc_Paused){
                stopSentencePlayer();
                setEngAu(R.raw.default_acc_audio);
                wholeTextPlayer.start();
                setPlayerState(PlayerState_DefAcc);
            }else if (playerState == PlayerState_DefAcc) {
                wholeTextPlayer.pause();
                setPlayerState(PlayerState_Def_Paused);
            } else if (playerState == PlayerState_Def_Paused) {
                wholeTextPlayer.start();
                setPlayerState(PlayerState_DefAcc);
            } else {
                setEngAu(R.raw.default_acc_audio);
                wholeTextPlayer.start();
                setPlayerState(PlayerState_DefAcc);
            }
        }
    });

    final Button btn_scottish_acc_whole = (Button) findViewById(R.id.btn_scottish_acc_whole);
    btn_scottish_acc_whole.setOnClickListener(new View.OnClickListener() {
        public void onClick(View arg0) {//problem here is
            if (playerState == PlayerState_DefAcc) {
                stopSentencePlayer();
                setEngAu(R.raw.scottish_acc_audio);
                wholeTextPlayer.start();
                setPlayerState(PlayerState_ScAcc);
            }else if (playerState == PlayerState_Def_Paused){
                stopSentencePlayer();
                setEngAu(R.raw.scottish_acc_audio);
                wholeTextPlayer.start();
                setPlayerState(PlayerState_ScAcc);
            }else
            if (playerState == PlayerState_ScAcc) {
                wholeTextPlayer.pause();
                setPlayerState(PlayerState_Sc_Paused);
            } else if (playerState == PlayerState_Sc_Paused) {
                wholeTextPlayer.start();
                setPlayerState(PlayerState_ScAcc);
            } else {
                setEngAu(R.raw.scottish_acc_audio);
                wholeTextPlayer.start();
                setPlayerState(PlayerState_ScAcc);
            }
        }
    });
}

private final int PlayerState_Def_Paused = 1;
private final int PlayerState_Sc_Paused = 2;
private final int PlayerState_DefAcc = 3;
private final int PlayerState_ScAcc = 4;

private int playerState;

private void setPlayerState(int state) {
    playerState = state;
}

public void setEngAu(int engAu) {
    wholeTextPlayer = MediaPlayer.create(this, engAu);
    seekBar.setProgress(0);
    seekBar.setMax(100);
    updateSeekBar();
}

public void updateSeekBar() {
    handler.postDelayed(mUpdateTimeTask, 100);
}

private Runnable mUpdateTimeTask = new Runnable() {
    public void run() {
        long totalDuration = wholeTextPlayer.getDuration();
        long currentDuration = wholeTextPlayer.getCurrentPosition();
        songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration));
        songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration));
        int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration));
        seekBar.setProgress(progress);
        handler.postDelayed(this, 100);
    }
};

public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
}

public void onStartTrackingTouch(SeekBar seekBar) {
    handler.removeCallbacks(mUpdateTimeTask);
}

public void onStopTrackingTouch(SeekBar seekBar) {
    handler.removeCallbacks(mUpdateTimeTask);
    int totalDuration = wholeTextPlayer.getDuration();
    int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration);
    wholeTextPlayer.seekTo(currentPosition);
    updateSeekBar();
}

private void stopSentencePlayer() {
    if(wholeTextPlayer !=null){
        try{
            wholeTextPlayer.release();
        }catch(Exception e){

            e.printStackTrace();
        }
    }
}

@Override
public void onBackPressed(){
    if(wholeTextPlayer != null){

            wholeTextPlayer.release();

        }
    finish();
    super.onBackPressed();
}

}

Another option could be to return to the same state of the screen that started the media player and in that case the audio could be paused, etc, but it seems to exceed my capabilities :( The player can play in the background, that's fine.

I hope I captured the right part. I am only a novice :)

1-06 17:27:02.909    6596-6596/com.tanuljangolulmenetkozben.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.IllegalStateException
        at android.media.MediaPlayer.getDuration(Native Method)
        at com.tanuljangolulmenetkozben.app.Lesson1Grammar$4.run(Lesson1Grammar.java:128)
        at android.os.Handler.handleCallback(Handler.java:587)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:130)
        at android.app.ActivityThread.main(ActivityThread.java:3705)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:507)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
        at dalvik.system.NativeStart.main(Native Method)
11-06 17:27:06.022    1675-1835/? E/Omap4ALSA﹕ called drain&close'

Solution

  • As I commented, the Handler continues to run whereas your Activity is destroying when user hits the onBackPressed(). Therefore, you have to check if this Handler is running and stop it as you already did in onStopTrackingTouch() method:

    public void onStopTrackingTouch(SeekBar seekBar) {
        handler.removeCallbacks(mUpdateTimeTask);
        ...
    }
    

    So, onBackPressed should looks like:

    @Override
    public void onBackPressed() {
        if (wholeTextPlayer != null) {
            wholeTextPlayer.release();
    
            if (handler != null)
                handler.removeCallbacks(null);
        }
        finish();
        super.onBackPressed();
    }
    

    Another good behaviour should to stop it in onPause or onStop:

    @Override
    protected void onStop() {
        super.onStop();
        if (handler != null)
            handler.removeCallbacks(null);
    }