I tried a lot of methods, I made a lot of changes on my code, I read Android MediaPlayer document, I tried StackOverflow examples but none of them could solve my problem.
My problem: When I press the home button of emulator or phone then reopen the app it is starting from the beginning.
Hope you can help me. Thanks in advance.
Here is my code :
public class Mediaplayer extends Activity implements OnCompletionListener,
OnErrorListener, OnInfoListener, OnPreparedListener,
OnSeekCompleteListener, OnVideoSizeChangedListener,
SurfaceHolder.Callback, MediaController.MediaPlayerControl {
Display currentDisplay;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
MediaPlayer mediaPlayer;
MediaController controller;
int videoWidth = 0;
int videoHeight = 0;
boolean readyToPlay = false;
public final static String LOGTAG = "CUSTOM_VIDEO_PLAYER";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.video);
surfaceView = (SurfaceView) this.findViewById(R.id.SurfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnVideoSizeChangedListener(this);
mediaPlayer.setWakeMode(getApplicationContext(),
PowerManager.PARTIAL_WAKE_LOCK);
String filePath = "http://cdn.example.com/wp-content/uploads/Almost.Human-S01E10.mp4";
try {
mediaPlayer.setDataSource(filePath);
} catch (IllegalArgumentException e) {
Log.v(LOGTAG, e.getMessage());
finish();
} catch (IllegalStateException e) {
Log.v(LOGTAG, e.getMessage());
finish();
} catch (IOException e) {
Log.v(LOGTAG, e.getMessage());
finish();
}
controller = new MediaController(this);
currentDisplay = getWindowManager().getDefaultDisplay();
}
public void surfaceCreated(SurfaceHolder holder) {
// Log.v(LOGTAG, "surfaceCreated Called");
mediaPlayer.setDisplay(holder);
try {
mediaPlayer.prepare();
} catch (IllegalStateException e) {
// Log.v(LOGTAG, e.getMessage());
finish();
} catch (IOException e) {
// Log.v(LOGTAG, e.getMessage());
finish();
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.v(LOGTAG, "surfaceChanged Called");
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v(LOGTAG, "surfaceDestroyed Called");
}
public void onCompletion(MediaPlayer mp) {
Log.v(LOGTAG, "onCompletion Called");
finish();
}
public boolean onError(MediaPlayer mp, int whatError, int extra) {
Log.v(LOGTAG, "onError Called");
if (whatError == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
Log.v(LOGTAG, "Media Error, Server Died " + extra);
} else if (whatError == MediaPlayer.MEDIA_ERROR_UNKNOWN) {
Log.v(LOGTAG, "Media Error, Error Unknown " + extra);
}
return false;
}
public boolean onInfo(MediaPlayer mp, int whatInfo, int extra) {
if (whatInfo == MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING) {
Log.v(LOGTAG, "Media Info, Media Info Bad Interleaving " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {
Log.v(LOGTAG, "Media Info, Media Info Not Seekable " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_UNKNOWN) {
Log.v(LOGTAG, "Media Info, Media Info Unknown " + extra);
} else if (whatInfo == MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING) {
Log.v(LOGTAG, "MediaInfo, Media Info Video Track Lagging " + extra);
/*
* Android Version 2.0 and Higher } else if (whatInfo ==
* MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
* Log.v(LOGTAG,"MediaInfo, Media Info Metadata Update " + extra);
*/
}
return false;
}
public void onPrepared(MediaPlayer mp) {
Log.v(LOGTAG, "onPrepared Called");
videoWidth = mp.getVideoWidth();
videoHeight = mp.getVideoHeight();
if (videoWidth > currentDisplay.getWidth()
|| videoHeight > currentDisplay.getHeight()) {
float heightRatio = (float) videoHeight
/ (float) currentDisplay.getHeight();
float widthRatio = (float) videoWidth
/ (float) currentDisplay.getWidth();
if (heightRatio > 1 || widthRatio > 1) {
if (heightRatio > widthRatio) {
videoHeight = (int) Math.ceil((float) videoHeight
/ (float) heightRatio);
videoWidth = (int) Math.ceil((float) videoWidth
/ (float) heightRatio);
} else {
videoHeight = (int) Math.ceil((float) videoHeight
/ (float) widthRatio);
videoWidth = (int) Math.ceil((float) videoWidth
/ (float) widthRatio);
}
}
}
surfaceView.setLayoutParams(new LinearLayout.LayoutParams(videoWidth,
videoHeight));
mp.start();
controller.setMediaPlayer(this);
controller.setAnchorView(this.findViewById(R.id.MainView));
controller.setEnabled(true);
controller.show();
}
@Override
protected void onPause() {
super.onPause();
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
} else {
return;
}
}
public void onSeekComplete(MediaPlayer mp) {
Log.v(LOGTAG, "onSeekComplete Called");
}
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.v(LOGTAG, "onVideoSizeChanged Called");
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
public int getBufferPercentage() {
return 0;
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public void pause() {
mediaPlayer.pause();
}
public void seekTo(int pos) {
mediaPlayer.seekTo(pos);
}
public void start() {
mediaPlayer.start();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
controller.show();
return false;
}
@Override
public int getAudioSessionId() {
// TODO Auto-generated method stub
return 0;
}
}
I understand you have accepted an answer but I'll explain what the problem was based on your comments on your question and the comments from you and Nana on Nana's answer.
SurfaceView
is destroyed when it is no longer visible and recreated when it becomes visible again.mp.pause()
in your Activity
onPause()
method.SurfaceView
is recreated.surfaceCreated
method you are calling mp.prepare()
but at this point mp
is in a paused state and calling prepare()
on a paused Mediaplayer
will throw an IllegalStateException
.try / catch
block which catches IllegalStateException
and calls finish()
- this is why the first attempt to restart the app from the 'recent' list causes the the Activity
to be destroyed.Activity
has been destroyed it will go through a full creation (with onCreate(..)
being called. This is why it starts from the beginning.The answer from Nana is a workaround but it will still mean having to use two attempts to restart your Activity
from the 'recent' list.
Unfortunately the MediaPlayer
class is lacking in methods for checking the 'state' with isPlaying
being the only useful method for any state. It's a shame the class devs didn't think to add a getState()
method (or similar) to allow checking for whether it's started, playing, stopped, paused etc.
One way of preventing the IllegalStateException
would be to have a boolean called isPaused
(for example) then modify your Activity
onPause()
as follows...
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
isPaused = true;
}
...and in surfaceCreated(...)
...
try {
if (isPaused) {
mpStart();
isPaused = false;
}
else
mediaPlayer.prepare();
}
// catch blocks here