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>