Search code examples
androiddrag-and-dropandroid-cameramedia-playersurfaceview

MediaPlayer is not working on the first run


I added a MediaPlayer to my app. It works fine but the first time I call my surface and I initialize the MediaPlayer the texture becomes Visible but its white, no video in it (but the sound is working and my logs said that its working fine).

After the first try, it works perfectly. But I can't find the reason why it's not working in a first try. Here is my code:

/////////
     mVideoView = (TextureView) mRootView.findViewById(R.id.show_video_content);
        mVideoView.setSurfaceTextureListener(this);
////////
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Log.i(TAG, "InicializoSurface. Width: " + width + "  HEIGHT:" + height);
        Log.i(TAG, "InicializoSurface. Width: " + mVideoView.getMeasuredWidth() + "  HEIGHT:" + mVideoView.getMeasuredHeight());
        Log.i(TAG, "View transform. Width: " + mVideoView.getWidth() + "  HEIGHT:" + mVideoView.getHeight());


        mMediaSurface = new Surface(mVideoView.getSurfaceTexture());
        initializeMediaPlayer();

    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {

        if (mMediaPlayer != null) {
            // Make sure we stop video and release resources when activity is destroyed.
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        return false;
    }
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

This is my Custom MediaPlayer and the event that I call when I initialize the surface:

   private class CustomMediaPlayer extends MediaPlayer implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener {

    SurfaceHolder mVideoHolder;

    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        if (mediaPlayer != null) {
            mediaPlayer.start();
        }
    }
    @Override
    public void onPrepared(MediaPlayer mediaPlayer) {
        Log.i(TAG,"video preparado");
        mMediaPrepared = true;
    }
}

 private void initializeMediaPlayer(){

    mMediaPlayer = new CustomMediaPlayer();
    Uri uri = Uri.parse(mCameraDataAdapter.getList().get(0).getPath());

    try {
        mMediaPlayer.setDataSource(mActivity, uri);
        mMediaPlayer.setSurface(mMediaSurface);
        mMediaPlayer.prepareAsync();
        mMediaPlayer.setOnPreparedListener(mMediaPlayer);
        mMediaPlayer.setOnCompletionListener(mMediaPlayer);


    } catch (IOException e) {
        e.printStackTrace();
    }


}

Finally I call the start() in my onDragListener:

      case DragEvent.ACTION_DRAG_STARTED:

                if (mCameraDataAdapter.getFirstElement().equalsIgnoreCase("video")) {
                    mThumbnailContainer.setVisibility(View.VISIBLE);
                    mVideoView.setVisibility(View.VISIBLE);


                    Log.i(TAG, "X: " + mVideoView.getX() + "Y: " + mVideoView.getY());


                    if (mVideoView.isAvailable()) {
                        onSurfaceTextureAvailable(mVideoView.getSurfaceTexture(), mVideoView.getWidth(), mVideoView.getHeight());
                    }

                    if (mMediaPlayer == null) {
                        initializeMediaPlayer();
                    }


                    if (mMediaPrepared) {
                        Log.i(TAG,"Comienzo Video");
                        mMediaPlayer.start();
                    }

                } else {
                    mThumbnailContainer.setVisibility(View.VISIBLE);
                    mImageContainer.setVisibility(View.VISIBLE);
                }
                mPreviewThumbIcon.setVisibility(View.INVISIBLE);
                return true;

I already tried to change my prepare() for a prepareAsync(), or using always a "visible" view, but I can't find the reason why it's not working.


Solution

  • Reset your MediaPlayer after every use inside your Drop & Drag method: Action_drag_ended:

    case DragEvent.ACTION_DRAG_STARTED:
    
    selected = null;
    
    if (mCameraDataAdapter.getFirstElement().equalsIgnoreCase("video")) {
    
        mImageContainer.setVisibility(View.INVISIBLE);
        mVideoView.setVisibility(View.VISIBLE);
        //SurfaceTexture is not called if the Texture is already available, so we call it anyway
        if (mVideoView.isAvailable()) {
            onSurfaceTextureAvailable(mVideoView.getSurfaceTexture(), mVideoView.getMeasuredWidth(), mVideoView.getMeasuredHeight());
        }
    
    } else {
        mVideoView.setVisibility(View.INVISIBLE);
        mImageContainer.setVisibility(View.VISIBLE);
    }
    mPreviewThumbIcon.setVisibility(View.INVISIBLE);
    return true;
    

    Also, put the Mediaplayer.start in your custom PreparedListener.

    private class CustomMediaPlayer extends MediaPlayer implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener {
    
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        if (mediaPlayer != null) {
            mediaPlayer.start();
        }
    }
    //We start the video when its available
    @Override
    public void onPrepared(MediaPlayer mediaPlayer) {
        Log.i(TAG,"Video Prepare");
        mediaPlayer.start();
    }
    }
    

    Hope it will help you. Good luck!