dleal
dleal

Reputation: 660

prepareAsync of MediaPlayer in one Activity, play in another

I am developing an application that, among other things, plays some video files (streaming). I would like to prepare the MediaPlayer in one activity but play the video once it is ready in another activity, so that the user can navigate through the content of the first activity to kill some time. Is this possible?

There is an static MediaPlayer defined in the Application class, like this:

public class EGDF_App extends Application {

    private static MediaPlayer mediaPlayer = null;

    public static MediaPlayer getMediaPlayer() {
        if(mediaPlayer == null)
            return new MediaPlayer();
        else
            return mediaPlayer;
    }

}

I have a button with a text (Load video). This text is changed when the video is ready, and when the user clicks on it, it triggers the following activity.

The problem is that I get the following error in LogCat:

09-06 20:43:34.606: D/ChapterPlayer(31999): surfaceCreated called
09-06 20:43:34.684: V/ChapterPlayer(31999): startVideoPlayback
09-06 20:43:34.684: E/MediaPlayer(31999): start called in state 1
09-06 20:43:34.684: E/MediaPlayer(31999): error (-38, 0)
09-06 20:43:34.684: D/ChapterPlayer(31999): surfaceChanged called
09-06 20:43:34.700: E/MediaPlayer(31999): Attempt to call getDuration without a valid mediaplayer
09-06 20:43:34.715: E/MediaPlayer(31999): Error (-38,0)
09-06 20:43:34.715: D/ChapterPlayer(31999): onCompletion called
09-06 20:43:34.751: E/MediaPlayer(31999): Attempt to call getDuration without a valid mediaplayer

This is the code contained in the first Activity:

public void watchChapter(View view){
    Log.i("Button", "Watch chapter button PRESSED");
    Button b = (Button) view;
    String loadChapter = getString(R.string.load_chapter_button_text);
    String watchChapter = getString(R.string.watch_chapter_button_text);

    if(((String) b.getText()).equals(loadChapter)){ 
        prepareVideo(view);

    }else if(((String) b.getText()).equals(watchChapter)){  

        Intent intent = new Intent(this,ChapterAsyncMediaPlayerActivity.class);
        intent.putExtra(Constants.chapterVideoResParse, getIntent().getExtras().getString(Constants.chapterVideoResParse));
        intent.putExtra("duration", String.valueOf(duration));
        startActivity(intent);
    }


}

private void prepareVideo(View view){
    MediaPlayer mMediaPlayer;
    String path;
    final Button button = (Button) view;
    String resource = extras.getString(Constants.chapterVideoResParse);
    path = SecurityHandler.obtainURL(resource, this.getResources().openRawResource(R.raw.output), 10);

    try {
        // Gets the media player and set the listeners
        mMediaPlayer = EGDF_App.getMediaPlayer();
        mMediaPlayer.setDataSource(path);
        mMediaPlayer.prepareAsync();
        mMediaPlayer.setOnPreparedListener(new OnPreparedListener(){

            @Override
            public void onPrepared(MediaPlayer mp) {
                button.setText(getString(R.string.watch_chapter_button_text));
                Log.i("MediaPlayer", "MediaPlayer ready");
                duration = mp.getDuration();
                Log.i("Video duration", String.valueOf(mp.getDuration()));
            }

        });
        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

And this is the code in the second Activity:

public class ChapterAsyncMediaPlayerActivity extends Activity implements
OnBufferingUpdateListener, OnCompletionListener,
OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback, MediaPlayerControl {

    private static final String TAG = "ChapterPlayer";
    private int mVideoWidth;
    private int mVideoHeight;
    private MediaPlayer mMediaPlayer;
    private MediaController mController;
    private SurfaceView mPreview;
    private SurfaceHolder holder;
//  private String path;
//  private boolean mIsVideoSizeKnown = false;
    private boolean mIsVideoReadyToBePlayed = false;

    private Handler handler = new Handler();

    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chapter_media_player);
        mPreview = (SurfaceView) findViewById(R.id.mediaPlayerSurface);
        holder = mPreview.getHolder();
        holder.addCallback(this);
        holder.setKeepScreenOn(true);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mController.show();
        return false;
    }

    private void playVideo() {
        doCleanUp();
        try {

            // Create a new media player and set the listeners
            mMediaPlayer = EGDF_App.getMediaPlayer();
//          mMediaPlayer.setDataSource(path);
            mMediaPlayer.setDisplay(holder);
//          mMediaPlayer.prepareAsync();
            mMediaPlayer.setOnBufferingUpdateListener(this);
            mMediaPlayer.setOnCompletionListener(this);
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setOnVideoSizeChangedListener(this);
            mMediaPlayer.setScreenOnWhilePlaying(true);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mController = new MediaController(this);

        } catch (Exception e) {
            Log.e(TAG, "error: " + e.getMessage(), e);
        }
    }

    public void onPrepared(MediaPlayer mediaplayer) {
        Log.d(TAG, "onPrepared called");
        mIsVideoReadyToBePlayed = true;
        mController.setMediaPlayer(this);
        mController.setAnchorView(findViewById(R.id.mediaPlayerSurface));
        handler.post(new Runnable(){

            @Override
            public void run() {

                mController.setEnabled(true);
                mController.show();

            }
        });
        if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {

            startVideoPlayback();
        }
    }

    public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
        Log.d(TAG, "surfaceChanged called");

    }

    public void surfaceDestroyed(SurfaceHolder surfaceholder) {
        Log.d(TAG, "surfaceDestroyed called");
    }

    public void surfaceCreated(SurfaceHolder holder) {
        Log.d(TAG, "surfaceCreated called");
        playVideo();
        mIsVideoReadyToBePlayed = true;
        mController.setMediaPlayer(this);
        mController.setAnchorView(findViewById(R.id.mediaPlayerSurface));
        handler.post(new Runnable(){

            @Override
            public void run() {

                mController.setEnabled(true);
                mController.show();

            }
        });
        if (mIsVideoReadyToBePlayed) {
            startVideoPlayback();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mMediaPlayer.pause();
    }

    @Override
    protected void onRestart() {
        super.onPause();
        mMediaPlayer.start();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        releaseMediaPlayer();
        doCleanUp();
    }

    private void releaseMediaPlayer() {
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    private void doCleanUp() {
        mVideoWidth = 0;
        mVideoHeight = 0;
        mIsVideoReadyToBePlayed = false;
    }

    private void startVideoPlayback() {
        Log.v(TAG, "startVideoPlayback");
        holder.setFixedSize(mVideoWidth, mVideoHeight);
        mMediaPlayer.start();
        mMediaPlayer.setScreenOnWhilePlaying(true);
    }

    @Override
    public boolean canPause() {
        return true;
    }

    @Override
    public boolean canSeekBackward() {
        return true;
    }

    @Override
    public boolean canSeekForward() {
        return true;
    }

    @Override
    public int getBufferPercentage() {
        return 0;
    }

    @Override
    public int getCurrentPosition() {
        if(mMediaPlayer != null)
            return mMediaPlayer.getCurrentPosition();
        else
            return 0;
    }

    @Override
    public int getDuration() {
        if(mMediaPlayer != null)
            return mMediaPlayer.getDuration();
        else
            return 0;
    }

    @Override
    public boolean isPlaying() {
        if(mMediaPlayer != null)
            return mMediaPlayer.isPlaying();
        else
            return false;
    }

    @Override
    public void pause() {
        if(mMediaPlayer != null)
            mMediaPlayer.pause();       
    }

    @Override
    public void seekTo(int pos) {
        mMediaPlayer.seekTo(pos);       
    }

    @Override
    public void start() {
        if(mMediaPlayer != null)
            mMediaPlayer.start();
    }

    public void onBufferingUpdate(MediaPlayer arg0, int percent) {
        Log.d(TAG, "onBufferingUpdate percent:" + percent);

    }

    public void onCompletion(MediaPlayer arg0) {
        Log.d(TAG, "onCompletion called");
    }

    @Override
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
        Log.v(TAG, "onVideoSizeChanged called");
        if (width == 0 || height == 0) {
            Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")");
            return;
        }
        mVideoWidth = width;
        mVideoHeight = height;
        if (mIsVideoReadyToBePlayed) {
            startVideoPlayback();
        }
    }
}

I would appreciate some help or advice. Thanks!

Upvotes: 1

Views: 1950

Answers (1)

Glebbb
Glebbb

Reputation: 356

I don't think you're saving the MediaPlayer in your application, you're just returning a new instance of it. Try changing it as so:

public static MediaPlayer getMediaPlayer() {
    if(mediaPlayer == null) {
        mediaPlayer = new MediaPlayer();
    }
    return mediaPlayer;
}

Upvotes: 1

Related Questions