1

My Android App is unable to play the music again after Hold mode is on/off.

My code is working fine at the beginning (the song sounds). But when the user press the hold button the app can't continue playing (when is back to the screen again after the hold).

By debugging I have checked that when you press the hold button (to restart the mobile), you enter inside onResume (obvious) but mediaPlayer.prepare() throws java.lang.IllegalStateException (captured in the catch block) with the message: prepareAsync called in state 0

After onResume() I called the method play() and it throws these errors:

Attempt to perform seekTo in wrong state

error (-38, 0)

Attempt to call getDuration without a valid mediaplayer

error (-38, 0)

Any idea? :S

This is my code: Fragment.java

public class FragmentMediaPlayer extends Fragment implements OnSeekBarChangeListener {

    private MediaPlayer mediaPlayer;
    public TextView duration;
    private double timeElapsed = 0, finalTime = 0;
    private int forwardTime = 5000, backwardTime = 5000;
    private Handler durationHandler = new Handler();
    private SeekBar seekBar;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View rootView = inflater.inflate(R.layout.media_player, container,
                false);

        // initialize views
        initializeViews(rootView);

        return rootView;
    }

    public void initializeViews(View rootView) {
        mediaPlayer = MediaPlayer.create(getActivity(), R.raw.song);
        try {
            mediaPlayer.prepare();
        } catch (IllegalStateException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finalTime = mediaPlayer.getDuration();
        duration = (TextView) rootView.findViewById(R.id.songDuration);
        duration.setText(String.format(
                "%d min, %d sec",
                0,0));
        
        seekBar = (SeekBar) rootView.findViewById(R.id.seekBar);

        seekBar.setMax((int) finalTime);
        seekBar.setOnSeekBarChangeListener(this);
        
        ImageButton playButton = (ImageButton) rootView.findViewById(R.id.media_play);
        playButton.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         play();
                     } 
           }); 
        
        ImageButton media_pause = (ImageButton) rootView.findViewById(R.id.media_pause);
        media_pause.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         pause(v);
                     } 
           }); 
        
        ImageButton media_ff = (ImageButton) rootView.findViewById(R.id.media_ff);
        media_ff.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         forward(v);
                     } 
           }); 
        
        ImageButton media_rew = (ImageButton) rootView.findViewById(R.id.media_rew);
        media_rew.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         rewind(v);
                     } 
           }); 
    }

    // play mp3 song
    public void play() {        
        timeElapsed = mediaPlayer.getCurrentPosition();
        seekBar.setProgress((int) timeElapsed);
        mediaPlayer.seekTo((int) timeElapsed) ;
        mediaPlayer.start();
        durationHandler.postDelayed(updateSeekBarTime, 100);
    }

    // handler to change seekBarTime
    private Runnable updateSeekBarTime = new Runnable() {
        public void run() {
            // get current position
            timeElapsed = mediaPlayer.getCurrentPosition();
            // set seekbar progress
            seekBar.setProgress((int) timeElapsed);
            // set time remaing
            //double timeRemaining = finalTime - timeElapsed;
            duration.setText(String.format(
                    "%d min, %d sec",
                    TimeUnit.MILLISECONDS.toMinutes((long) timeElapsed),
                    TimeUnit.MILLISECONDS.toSeconds((long) timeElapsed)
                            - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS
                                    .toMinutes((long) timeElapsed))));

            // repeat yourself that again in 100 miliseconds
            durationHandler.postDelayed(this, 100);         
        }
    };
    
    // pause mp3 song
    public void pause(View view) {
        mediaPlayer.pause();    
        timeElapsed = mediaPlayer.getCurrentPosition();
    }

    // go forward at forwardTime seconds
    public void forward(View view) {
        // check if we can go forward at forwardTime seconds before song endes
        if ((timeElapsed + forwardTime) <= finalTime) {
            timeElapsed = timeElapsed + forwardTime;

            // seek to the exact second of the track
            mediaPlayer.seekTo((int) timeElapsed);
        }
    }

    // go backwards at backwardTime seconds
    public void rewind(View view) {
        // check if we can go back at backwardTime seconds after song starts
        if ((timeElapsed - backwardTime) > 0) {
            timeElapsed = timeElapsed - backwardTime;

            // seek to the exact second of the track
            mediaPlayer.seekTo((int) timeElapsed);
        }
    }   

    @Override
    public void onResume() {
        super.onResume();
        try {
            mediaPlayer.prepare();
        } catch (IllegalStateException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        play();
    }
    
    @Override
    public void onPause() {
        super.onPause();
        mediaPlayer.pause();
    }

    @Override
    public void onStop() {
        // Stop updates and Disconnect from LocationServices
        mediaPlayer.stop();
        durationHandler.removeCallbacks(updateSeekBarTime);
        super.onStop();
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 
        if(fromUser) { 
            mediaPlayer.seekTo(progress); 
            seekBar.setProgress(progress);
        }
    }
    
    @Override
    public void onStartTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onStopTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub
        
    }

And here is my layout.xml:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    android:orientation="vertical" >

<LinearLayout 
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/songName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/play_text" />

    <TextView
        android:id="@+id/songDuration"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="30dp"
        android:layout_marginBottom="30dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >

        <ImageButton
            android:id="@+id/media_rew"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:contentDescription="@string/rewind"
            android:src="@android:drawable/ic_media_rew" />

        <ImageButton
            android:id="@+id/media_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:contentDescription="@string/pause"
            android:src="@android:drawable/ic_media_pause" />

        <ImageButton
            android:id="@+id/media_play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:contentDescription="@string/play"
            android:src="@android:drawable/ic_media_play" />

        <ImageButton
            android:id="@+id/media_ff"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:contentDescription="@string/forward"
            android:src="@android:drawable/ic_media_ff" />
    </LinearLayout>    

</LinearLayout>
</ScrollView>
Community
  • 1
  • 1
Ignacio Rubio
  • 1,354
  • 14
  • 25
  • After I have read several posts, I have put this in my code and quited mediaPlayer.start() from the method play(), but still have the same problem: mediaPlayer.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); } }); – Ignacio Rubio Oct 31 '14 at 12:12
  • I have checked the MediaPlayer state diagram: http://developer.android.com/images/mediaplayer_state_diagram.gif I'm calling start() after pause(). I'm missing something... – Ignacio Rubio Oct 31 '14 at 12:21
  • You should not call `prepare()` in `Paused` state. Only `start(), stop(), seekTo()` are valid in `Paused` state. In your case just try calling `play()` method in `onResume()`. – Manish Mulimani Nov 03 '14 at 15:28
  • 1
    In addition to above comment, since `MediaPlayer.stop()` is called in `onStop()`, `MediaPlayer.prepare()` has to be called in `onStart()` callback. – Manish Mulimani Nov 03 '14 at 15:31
  • possible duplicate of [Android MediaPlayer Problems :"Error (-38 , 0) " and "stop called in state 1"](http://stackoverflow.com/questions/11913108/android-mediaplayer-problems-error-38-0-and-stop-called-in-state-1) – rds Jun 22 '15 at 08:56

1 Answers1

1

I think this code should fix your problems.

public class FragmentMediaPlayer extends Fragment implements OnSeekBarChangeListener {

    private MediaPlayer mediaPlayer;
    public TextView duration;
    private int timeElapsed = 0, finalTime = 0;
    private int forwardTime = 5000, backwardTime = 5000;
    private Handler durationHandler = new Handler();
    private SeekBar seekBar;
    private boolean pausedFromButton = false;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View rootView = inflater.inflate(R.layout.media_player, container,
                false);

        // Initialize different views from the layout
        duration = (TextView) rootView.findViewById(R.id.songDuration);
        duration.setText(String.format(
                "%d min, %d sec",
                0,0));

        seekBar = (SeekBar) rootView.findViewById(R.id.seekBar);
        seekBar.setOnSeekBarChangeListener(this);

        ImageButton playButton = (ImageButton) rootView.findViewById(R.id.media_play);
        playButton.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         play();
                     } 
           }); 

        ImageButton media_pause = (ImageButton) rootView.findViewById(R.id.media_pause);
        media_pause.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         pause();
                     } 
           }); 

        ImageButton media_ff = (ImageButton) rootView.findViewById(R.id.media_ff);
        media_ff.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         forward();
                     } 
           }); 

        ImageButton media_rew = (ImageButton) rootView.findViewById(R.id.media_rew);
        media_rew.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         rewind();
                     } 
           }); 

        return rootView;
    }   

    @Override
    public void onResume() {
        super.onResume();   
        prepareMediaPlayer();   
        play();
    }

    @Override
    public void onPause() {
        super.onPause();
        //Not call pause because it's necessaty to distinguish between onPause() and when the user press the pause buttonn
        mediaPlayer.pause();
    }

    @Override
    public void onStop() {
        // Stop updates and Disconnect from Services
        mediaPlayer.stop();
        durationHandler.removeCallbacks(updateSeekBarTime);
        super.onStop();
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 
        if(fromUser) { 
            mediaPlayer.seekTo(progress); 
            seekBar.setProgress(progress);
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onStopTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub

    }

    /**
     * Prepare MediaPlayer and recover from bad status
     */
    private void prepareMediaPlayer() {
        mediaPlayer = MediaPlayer.create(getActivity(), R.raw.song);
        finalTime = mediaPlayer.getDuration();
        seekBar.setMax(finalTime);
        mediaPlayer.seekTo(timeElapsed);
        mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.start();
            }
        });
        mediaPlayer.setOnCompletionListener(new
                OnCompletionListener() {        
                    @Override
                    public void onCompletion(MediaPlayer arg0) {
                        pausedFromButton = true;
                    }
        });
    }

    /**
     * play mp3 song
     */
    public void play() {
        if(pausedFromButton) {
            prepareMediaPlayer();
            pausedFromButton = false;
        }       
        seekBar.setProgress(timeElapsed);
        durationHandler.postDelayed(updateSeekBarTime, 100);
    }

    /**
     * handler to change seekBarTime
     */
    private Runnable updateSeekBarTime = new Runnable() {
        public void run() {
            // get current position
            timeElapsed = mediaPlayer.getCurrentPosition();
            // set seekbar progress
            seekBar.setProgress(timeElapsed);
            // set time remaing
            //double timeRemaining = finalTime - timeElapsed;
            duration.setText(String.format(
                    "%d min, %d sec",
                    TimeUnit.MILLISECONDS.toMinutes((long) timeElapsed),
                    TimeUnit.MILLISECONDS.toSeconds((long) timeElapsed)
                            - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS
                                    .toMinutes((long) timeElapsed))));

            // repeat yourself that again in 100 miliseconds
            durationHandler.postDelayed(this, 100);         
        }
    };


    /**
     * pause mp3 song
     */
    public void pause() {
        mediaPlayer.pause();    
        timeElapsed = mediaPlayer.getCurrentPosition();
        pausedFromButton = true;
    }

    /**
     * go forward at forwardTime seconds
     */
    public void forward() {
        // check if we can go forward at forwardTime seconds before song endes
        if ((timeElapsed + forwardTime) <= finalTime) {
            timeElapsed = timeElapsed + forwardTime;

            // seek to the exact second of the track
            mediaPlayer.seekTo(timeElapsed);
        }
    }

    /**
     * go backwards at backwardTime seconds
     */
    public void rewind() {
        // check if we can go back at backwardTime seconds after song starts
        if ((timeElapsed - backwardTime) > 0) {
            timeElapsed = timeElapsed - backwardTime;

            // seek to the exact second of the track
            mediaPlayer.seekTo(timeElapsed);
        }
    }   


}
jVel
  • 76
  • 2