Nexus 6 and MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);

628 views Asked by At

Hi I'm trying to achieve an Activity with background made from video file. The solution posted below is working on most devices, except nexus 6 Android 5.1. The video is working, is scaled but is not cropped, so aspect ratio is not preserved.

Tested with Galaxy Note, HTC One m7, Xperia Z3, Nexus 5.

Here is the code:

public class MainActivity extends ActionBarActivity implements SurfaceHolder.Callback, OnClickListener
{
    private static final int VIDEO_START_HACK_DELAY = 0;

    private static final String BG_VIDEO_PATH = "/raw/construction";
    private SurfaceView mSurface;

    private Button mTour, mLogin;

    private MediaPlayer mMediaPlayer;

    private Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_start_main);
        setupUI();
    }

    private void setupUI()
    {
        mMediaPlayer = new MediaPlayer();
        mSurface = (SurfaceView) findViewById(R.id.surface);
        SurfaceHolder holder = mSurface.getHolder();
        holder.addCallback(this);

        mTour = (Button) findViewById(R.id.tour);
        mLogin = (Button) findViewById(R.id.login);

        mTour.setOnClickListener(this);
        mLogin.setOnClickListener(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        startVideo(holder);
    }

    @SuppressLint("NewApi")
    public void startVideo(SurfaceHolder holder)
    {
        String path = "android.resource://" + getPackageName() + BG_VIDEO_PATH;
        Uri uri = Uri.parse(path);

        try
        {
            android.view.ViewGroup.LayoutParams lp = mSurface.getLayoutParams();
            mMediaPlayer.setDisplay(holder);
            mMediaPlayer.setDataSource(this, uri);
            mMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
            mMediaPlayer.setLooping(true);
            mMediaPlayer.setOnPreparedListener(new OnPreparedListener()
            {

                @Override
                public void onPrepared(MediaPlayer mp)
                {
                    mHandler.postDelayed(new Runnable()
                    {

                        @Override
                        public void run()
                        {
                            mMediaPlayer.start();
                        }
                    }, VIDEO_START_HACK_DELAY);

                }
            });
            mMediaPlayer.prepareAsync();
        }
        catch (Exception e)
        {
            Log.e("VID", "Problem starting video bg", e);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {
        // TODO Auto-generated method stub
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        // TODO Auto-generated method stub

    }

    @Override
    public void onBackPressed()
    {
        mSurface.setVisibility(View.INVISIBLE);
        mMediaPlayer.stop();
        super.onBackPressed();
    }

    @Override
    protected void onDestroy()
    {
        mMediaPlayer.stop();
        mMediaPlayer.release();
        super.onDestroy();
    }
}

Here is layout file:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <SurfaceView 
        android:id="@+id/surface" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" />

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="40dp"
        android:gravity="center"
        android:orientation="vertical" >

        <Button
            android:id="@+id/tour"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
            android:padding="10dp"
            android:text="@string/ma_tour"/>

        <Button
            android:id="@+id/login"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:padding="10dp"
            android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
            android:text="@string/ma_log_in"/>

    </LinearLayout>

</RelativeLayout>

Target sdk is set to 22. Have you maybe experienced such behavior and can give any advice?

1

There are 1 answers

0
Ashish Pathak On

Here is how I did it in one of my applications:

  1. Set the OnPreparedListener on MediaPlayer object.

    mediaPlayer.setOnPreparedListener(this);

  2. When the public void onPrepared(MediaPlayer mp) is called, resize the SurfaceView so that it creates the illusion of cropped video. Log.v(LOG_TAG, "onPrepared called for MediaPlayer"); // Adjust the size of the video so it fits on the screen int videoWidth = mInitialVideoPlayer.getVideoWidth(); int videoHeight = mInitialVideoPlayer.getVideoHeight(); float videoProportion = (float) videoWidth / (float) videoHeight;

    ViewGroup.LayoutParams lp = mSplashVideoSurfaceView.getLayoutParams();
    
    // We always want to fill entire view port. So, we keep the smallest dimension and proportionately
    // scale the other dimension.
    if (videoWidth < videoHeight) {
        lp.width = UiUtils.sScreenWidth;
        lp.height = (int) ((float) UiUtils.sScreenWidth / videoProportion);
    } else {
        lp.width = (int) (videoProportion * (float) UiUtils.sScreenHeight);If you are targetting API level 14 and above, <code>TextureView</code> allows you to play cropped video
        lp.height = UiUtils.sScreenHeight;
    }
    Log.v(LOG_TAG, "old video size: " + videoWidth + ", " + videoHeight);
    Log.v(LOG_TAG, "screen  size: " + UiUtils.sScreenWidth + ", " + UiUtils.sScreenHeight);
    Log.v(LOG_TAG, "new video size: " + lp.width + ", " + lp.height);
    mSplashVideoSurfaceView.setLayoutParams(lp);