I\'m currently developing the android application ServeStream and I\'ve encountered and problem that I can\'t fix. My application will stream music and video using the android M
EDIT: Please note this solution does not work on 4.x devices - video simply never appears, only blank screen and I couldn't make it work there.
Here's a state machine that does the following:
1. plays short couple of seconds video /res/raw/anim_mp4.mp4 (procedure initiated in onCreate() method)
2. if user presses home button then returns to app it will seek video to start position and pause immediatelly (procedure initiated in onResume() method)
package com.test.video;
import android.app.Activity;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
public class MediaPlayerActivity extends Activity implements OnCompletionListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnSeekCompleteListener, SurfaceHolder.Callback {
private final int STATE_NOT_INITIALIZED = 0;
private final int STATE_INITIALIZING = 1;
private final int STATE_INITIALIZED = 2;
private final int STATE_SEEKING = 3;
private final int STATE_DELAYING = 4;
private final int STATE_PLAYING = 5;
private final int STATE_FINISHED = 6;
private final int STATE_RESUMED = 7;
private final int STATE_RESUMED_PREPARING = 8;
private final int STATE_RESUMED_PREPARED = 9;
private final int STATE_RESUMED_SEEKING = 10;
private int state = STATE_NOT_INITIALIZED;
private SurfaceView surface;
private MediaPlayer player;
private SurfaceHolder holder;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(Constants.TAG, "onCreate()");
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.mediaplayer);
surface = (SurfaceView) findViewById(R.id.idSurface);
holder = surface.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
@Override
protected void onStart() {
Log.d(Constants.TAG, "onStart()");
super.onStart();
state();
}
@Override
protected void onResume() {
Log.d(Constants.TAG, "onResume()");
super.onResume();
if (STATE_FINISHED == state) {
state = STATE_RESUMED;
state();
}
}
@Override
protected void onDestroy() {
Log.d(Constants.TAG, "onDestroy()");
super.onDestroy();
if (player != null) {
player.release();
player = null;
}
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
Log.d(Constants.TAG, "surfaceChanged()");
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
Log.d(Constants.TAG, "surfaceCreated()");
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
Log.d(Constants.TAG, "surfaceDestroyed()");
}
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(Constants.TAG, "onPrepared()");
state();
}
@Override
public void onCompletion(MediaPlayer mp) {
Log.d(Constants.TAG, "onCompletion()");
state();
}
@Override
public void onSeekComplete(MediaPlayer mediaplayer) {
Log.d(Constants.TAG, "onSeekComplete()");
state();
}
private class ResumeDelayed extends PlayDelayed {
protected void onPostExecute(Void result) {
Log.d(Constants.TAG, "ResumeDelayed.onPostExecute()");
state();
};
}
private void initPlayer() {
Log.d(Constants.TAG, "initPlayer()");
try {
if (player == null) {
player = new MediaPlayer();
player.setScreenOnWhilePlaying(true);
} else {
player.stop();
player.reset();
}
String uri = "android.resource://" + getPackageName() + "/" + R.raw.anim_mp4;
player.setDataSource(this, Uri.parse(uri));
player.setDisplay(holder);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
player.prepareAsync();
player.setOnCompletionListener(this);
player.setOnSeekCompleteListener(this);
} catch (Throwable t) {
Log.e(Constants.TAG, "Exception in media prep", t);
}
}
private class PlayDelayed extends AsyncTask {
@Override
protected Void doInBackground(Void... arg0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(Constants.TAG, "Can't sleep", e);
}
return null;
}
protected void onPostExecute(Void result) {
Log.d(Constants.TAG, "PlayDelayed.onPostExecute()");
initPlayer();
};
}
private void state() {
switch (state) {
case STATE_NOT_INITIALIZED:
state = STATE_INITIALIZING;
initPlayer();
break;
case STATE_INITIALIZING:
state = STATE_INITIALIZED;
new PlayDelayed().execute();
break;
case STATE_INITIALIZED:
state = STATE_SEEKING;
player.start();
player.seekTo(0);
break;
case STATE_SEEKING:
state = STATE_DELAYING;
player.pause();
new ResumeDelayed().execute();
break;
case STATE_DELAYING:
state = STATE_PLAYING;
player.start();
break;
case STATE_PLAYING:
state = STATE_FINISHED;
break;
case STATE_RESUMED:
state = STATE_RESUMED_PREPARING;
initPlayer();
break;
case STATE_RESUMED_PREPARING:
state = STATE_RESUMED_PREPARED;
new PlayDelayed().execute();
break;
case STATE_RESUMED_PREPARED:
state = STATE_RESUMED_SEEKING;
player.start();
player.seekTo(0);
break;
case STATE_RESUMED_SEEKING:
state = STATE_FINISHED;
player.pause();
break;
default:
break;
}
}
mediaplayer.xml layout:
AndroidManifest.xml looks like: