com.example.androidx.media.VideoViewTest.java Source code

Java tutorial

Introduction

Here is the source code for com.example.androidx.media.VideoViewTest.java

Source

/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.androidx.media;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import androidx.media.widget.MediaControlView2;
import androidx.media.widget.VideoView2;

/**
 * Test application for VideoView2/MediaControlView2
 */
@SuppressLint("NewApi")
public class VideoViewTest extends Activity {
    public static final String LOOPING_EXTRA_NAME = "com.example.androidx.media.VideoViewTest.IsLooping";
    public static final String USE_TEXTURE_VIEW_EXTRA_NAME = "com.example.androidx.media.VideoViewTest.UseTextureView";
    public static final String MEDIA_TYPE_ADVERTISEMENT = "com.example.androidx.media.VideoViewTest.MediaTypeAdvertisement";
    private static final String TAG = "VideoViewTest";

    private MyVideoView mVideoView = null;
    private float mSpeed = 1.0f;

    private MediaControlView2 mMediaControlView = null;

    private boolean mUseTextureView = false;
    private int mPrevWidth;
    private int mPrevHeight;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Remove title bar
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.video_activity);

        mVideoView = findViewById(R.id.video_view);

        String errorString = null;
        Intent intent = getIntent();
        Uri contentUri;
        if (intent == null || (contentUri = intent.getData()) == null || !contentUri.isAbsolute()) {
            errorString = "Invalid intent";
        } else {
            mUseTextureView = intent.getBooleanExtra(USE_TEXTURE_VIEW_EXTRA_NAME, false);
            if (mUseTextureView) {
                mVideoView.setViewType(VideoView2.VIEW_TYPE_TEXTUREVIEW);
            }

            mVideoView.setFullScreenRequestListener(new FullScreenRequestListener());
            mVideoView.setVideoUri(contentUri);

            mMediaControlView = new MediaControlView2(this);
            mVideoView.setMediaControlView2(mMediaControlView, 2000);
        }
        if (errorString != null) {
            showErrorDialog(errorString);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        if (mVideoView.isAttachedToWindow()) {
            mVideoView.getMediaController().getTransportControls().play();
            mVideoView.getMediaController().registerCallback(mMediaControllerCallback);
        } else {
            mVideoView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
                @Override
                public void onViewAttachedToWindow(View v) {
                    mVideoView.getMediaController().getTransportControls().play();
                    mVideoView.getMediaController().registerCallback(mMediaControllerCallback);
                }

                @Override
                public void onViewDetachedFromWindow(View v) {
                    // No need to remove callback here since MediaSession has already been
                    // destroyed.
                }
            });
        }
        setTitle(getViewTypeString(mVideoView));
    }

    @Override
    protected void onPause() {
        mVideoView.getMediaController().getTransportControls().pause();
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "onDestroy");
        mVideoView.getMediaController().unregisterCallback(mMediaControllerCallback);
        mVideoView.getMediaController().getTransportControls().stop();
        super.onDestroy();
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            int screenWidth = getResources().getDisplayMetrics().widthPixels;
            if (ev.getRawX() < (screenWidth / 2.0f)) {
                // TODO: getSpeed() not needed?
                mSpeed -= 0.1f;
            } else {
                mSpeed += 0.1f;
            }
            mVideoView.setSpeed(mSpeed);
            Toast.makeText(this, "speed rate: " + String.format("%.2f", mSpeed), Toast.LENGTH_SHORT).show();
        }
        return super.onTouchEvent(ev);
    }

    private void showErrorDialog(String errorMessage) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Playback error").setMessage(errorMessage).setCancelable(false)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        finish();
                    }
                }).show();
    }

    MediaControllerCompat.Callback mMediaControllerCallback = new MediaControllerCompat.Callback() {
        @Override
        public void onPlaybackStateChanged(PlaybackStateCompat state) {
            switch (state.getState()) {
            case PlaybackStateCompat.STATE_STOPPED:
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                break;
            case PlaybackStateCompat.STATE_ERROR:
                showErrorDialog("Error: (" + state.getErrorMessage() + ")");
                break;
            }
        }
    };

    private class FullScreenRequestListener implements VideoView2.OnFullScreenRequestListener {
        @Override
        public void onFullScreenRequest(View view, boolean fullScreen) {
            // TODO: Remove bottom controls after adding back button functionality.
            if (mPrevHeight == 0 && mPrevWidth == 0) {
                ViewGroup.LayoutParams params = mVideoView.getLayoutParams();
                mPrevWidth = params.width;
                mPrevHeight = params.height;
            }

            if (fullScreen) {
                // Remove notification bar
                getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                        WindowManager.LayoutParams.FLAG_FULLSCREEN);

                ViewGroup.LayoutParams params = mVideoView.getLayoutParams();
                params.width = ViewGroup.LayoutParams.MATCH_PARENT;
                params.height = ViewGroup.LayoutParams.MATCH_PARENT;
                mVideoView.setLayoutParams(params);
            } else {
                // Restore notification bar
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

                ViewGroup.LayoutParams params = mVideoView.getLayoutParams();
                params.width = mPrevWidth;
                params.height = mPrevHeight;
                mVideoView.setLayoutParams(params);
            }
            mVideoView.requestLayout();
            mVideoView.invalidate();
        }
    }

    /**
     * Extension of the stock android video view used to hook and override
     * keypress behavior.  Mainly used to make sure that certain keystrokes
     * don't automatically bring up the andriod MediaController widget (which
     * then steals focus)
     *
     * @author johngro@google.com (John Grossman)
     */
    public static class MyVideoView extends VideoView2 {
        private float mDX;
        private float mDY;

        public MyVideoView(Context context) {
            super(context);
        }

        public MyVideoView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public MyVideoView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDX = ev.getRawX() - getX();
                mDY = ev.getRawY() - getY();
                super.onTouchEvent(ev);
                return true;
            case MotionEvent.ACTION_MOVE:
                animate().x(ev.getRawX() - mDX).y(ev.getRawY() - mDY).setDuration(0).start();
                super.onTouchEvent(ev);
                return true;
            }
            return super.onTouchEvent(ev);
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (mVideoView.getViewType() == VideoView2.VIEW_TYPE_SURFACEVIEW) {
            mVideoView.setViewType(VideoView2.VIEW_TYPE_TEXTUREVIEW);
            Toast.makeText(this, "switch to TextureView", Toast.LENGTH_SHORT).show();
            setTitle(getViewTypeString(mVideoView));
        } else if (mVideoView.getViewType() == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
            mVideoView.setViewType(VideoView2.VIEW_TYPE_SURFACEVIEW);
            Toast.makeText(this, "switch to SurfaceView", Toast.LENGTH_SHORT).show();
            setTitle(getViewTypeString(mVideoView));
        }
    }

    private String getViewTypeString(VideoView2 videoView) {
        if (videoView == null) {
            return "Unknown";
        }
        int type = videoView.getViewType();
        if (type == VideoView2.VIEW_TYPE_SURFACEVIEW) {
            return "SurfaceView";
        } else if (type == VideoView2.VIEW_TYPE_TEXTUREVIEW) {
            return "TextureView";
        }
        return "Unknown";
    }
}