In this tutorial we will learn about VideoView. How to use it to stream a video.

What is a VideoView?

VideoView is a widget that displays a video file.

The VideoView class can load images from various sources (such as resources or content providers), takes care of computing its measurement from the video so that it can be used in any layout manager, and provides various display options such as scaling and tinting.

You can find VideoView API reference here.

Otherwise let’s look at sime examples.

Example 1: Kotlin Android – Stream Video using VideoView

This is a Kotlin ANdroid example on how to stream a video from online using VideoView.

Here is the demo screenshot of the project:

Step 1: Create Project

Start by creating an empty Android Studio project.

Step 2: Dependencies

No third party dependency is needed for this project.

Step 3: Design Layout

Add a VideoView, two ImageViews, a SeekBar as well as a TextView in your MainActivity’s layout as follows:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true" />

    <ImageView
        android:id="@+id/playPauseButton"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/videoView"
        android:layout_marginTop="5dp"
        android:src="@mipmap/play_button" />

    <ImageView
        android:id="@+id/stopButton"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_below="@+id/videoView"
        android:layout_marginLeft="2dp"
        android:layout_marginTop="5dp"
        android:layout_toRightOf="@id/playPauseButton"
        android:src="@mipmap/stop_button" />

    <TextView
        android:id="@+id/runningTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/videoView"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="15dp"
        android:layout_toRightOf="@id/stopButton"
        android:text="00:00"
        android:textColor="@android:color/black"
        android:textSize="16dp" />

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/videoView"
        android:layout_marginTop="10dp"
        android:layout_toRightOf="@id/runningTime" />

</RelativeLayout>

Step 4: Write Code

Replace your MainActivity with the following code:

MainActivity.kt

import android.app.ProgressDialog
import android.media.MediaPlayer
import android.net.Uri
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.util.Log
import android.view.View
import android.widget.*
import kotlin.concurrent.fixedRateTimer

//Always device to run this App
class MainActivity : AppCompatActivity(), MediaPlayer.OnCompletionListener,
        MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener, SeekBar.OnSeekBarChangeListener,
        View.OnClickListener {

    private val HLS_STREAMING_SAMPLE = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
    private var sampleVideoView: VideoView? = null
    private var seekBar: SeekBar? = null
    private var playPauseButton: ImageView? = null
    private var stopButton: ImageView? = null
    private var runningTime: TextView? = null
    private var currentPosition: Int = 0
    private var isRunning = false

    //Always device to run this App
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        sampleVideoView = findViewById<VideoView>(R.id.videoView)
        sampleVideoView?.setVideoURI(Uri.parse(HLS_STREAMING_SAMPLE))

        playPauseButton = findViewById<ImageView>(R.id.playPauseButton)
        playPauseButton?.setOnClickListener(this)

        stopButton = findViewById<ImageView>(R.id.stopButton)
        stopButton?.setOnClickListener(this)

        seekBar = findViewById<SeekBar>(R.id.seekBar)
        seekBar?.setOnSeekBarChangeListener(this)

        runningTime = findViewById<TextView>(R.id.runningTime)
        runningTime?.setText("00:00")

        Toast.makeText(this, "Buffering...Please wait", Toast.LENGTH_LONG).show()

        //Add the listeners
        sampleVideoView?.setOnCompletionListener(this)
        sampleVideoView?.setOnErrorListener(this)
        sampleVideoView?.setOnPreparedListener(this)
    }

    override fun onCompletion(mp: MediaPlayer?) {
        Toast.makeText(baseContext, "Play finished", Toast.LENGTH_LONG).show()
    }

    override fun onError(mp: MediaPlayer?, what: Int, extra: Int): Boolean {
        Log.e("video", "setOnErrorListener ")
        return true
    }

    override fun onPrepared(mp: MediaPlayer?) {
        seekBar?.setMax(sampleVideoView?.getDuration()!!)
        sampleVideoView?.start()

        val fixedRateTimer = fixedRateTimer(name = "hello-timer",
                initialDelay = 0, period = 1000) {
            refreshSeek()
        }

        playPauseButton?.setImageResource(R.mipmap.pause_button)
    }

    fun refreshSeek() {
        seekBar?.setProgress(sampleVideoView?.getCurrentPosition()!!);

        if (sampleVideoView?.isPlaying()!! == false) {
            return
        }

        var time = sampleVideoView?.getCurrentPosition()!! / 1000;
        var minute = time / 60;
        var second = time % 60;

        runOnUiThread {
            runningTime?.setText(minute.toString() + ":" + second.toString());
        }
    }

    var refreshTime = Runnable() {
        fun run() {

        }
    };

    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        //do nothing
    }

    override fun onStartTrackingTouch(seekBar: SeekBar?) {
        //do nothing
    }

    override fun onStopTrackingTouch(seekBar: SeekBar?) {
        sampleVideoView?.seekTo(seekBar?.getProgress()!!)
    }

    override fun onClick(v: View?) {
        if (v?.getId() == R.id.playPauseButton) {
            //Play video
            if (!isRunning) {
                isRunning = true
                sampleVideoView?.resume()
                sampleVideoView?.seekTo(currentPosition)
                playPauseButton?.setImageResource(R.mipmap.pause_button)
            } else { //Pause video
                isRunning = false
                sampleVideoView?.pause()
                currentPosition = sampleVideoView?.getCurrentPosition()!!
                playPauseButton?.setImageResource(R.mipmap.play_button)
            }
        } else if (v?.getId() == R.id.stopButton) {
            playPauseButton?.setImageResource(R.mipmap.play_button)
            sampleVideoView?.stopPlayback()
            currentPosition = 0
        }
    }
}

Run

Copy the code or download it in the link below, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author

Example 2: Kotlin Android VideoView – Play Local mp4 video

Learn VideoView using this simple example written in Kotlin. Learn how to play video files such as mp4 easily without much code. You need a VideoView widget for that and this example shows you how to use it to play mp4 file.

This example will show you how to load and play a video file located in our raw folder or directory.

Step 1: Create Project

Start by creating an empty Android Studio project.

Step 2: Dependencies

No external dependencies are needed for this.

Step 3: Add Video File

Add an mp4 file to your raw directory under the res folder. If you do not have such a directory then create it.

You can download a sample video file here

Step 4: Design Layout

Simply add VideoView to your xml layout as follows:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    tools:context=".MainActivity">

    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_marginEnd="20dp"
        android:layout_marginStart="20dp"/>

</LinearLayout>

Step 5: Play Video

First reference the video file path as follows:

        val filePlace = "android.resource://"+ packageName + "/raw/" + R.raw.video

Then set the path to the videoview using the setVideoUri() function as follows:

        videoView.setVideoURI(Uri.parse(filePlace))

Then set the MediaController then play the video using the start() function:


        videoView.setMediaController(MediaController(this))
        videoView.start()

Here’s the full code:

MainActivity.kt

import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.MediaController
import android.widget.VideoView

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val fileName = "video"
        val filePlace = "android.resource://"+ packageName + "/raw/" + R.raw.video
        val videoView = findViewById<VideoView>(R.id.videoView)
        videoView.setVideoURI(Uri.parse(filePlace))

        videoView.setMediaController(MediaController(this))
        videoView.start()
    }
}

Run

Copy the code or download it in the link below, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author
3. Code: Apache 2.0 License

More Examples

Here are more VideoView examples:

1. How to Create Custom VideoView

Step by step example on how to create a videoplayer based on custom videoview.

Here is the demo screenshot:

https://github.com/ZQiang94/VideoPalyer/raw/master/art/art.png

Step 1: Dependencies

No external dependencies are needed.

Step 2: Add Permissions

Add the following permissions in your AndroidManifest.xml:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />

Step 3: Create Animations

Create a folder inside the res directory and called animator and add the following two animations:

(a). enter_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="400"
    android:fromYDelta="100%"
    android:toYDelta="0"/>

(b). exit_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromYDelta="0"
    android:toYDelta="100%"
    android:duration="400">
    </translate>

Step 4: Create Custom VideoView

Create a custom videoView as shown below:

SimpleVideoView.java

package zqiang94.github.io.videopalyer;

import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.VideoView;

/**
 * <p>自定义ViewGroup,底部有控制面板的Video</p>
 */
public class SimpleVideoView extends RelativeLayout implements OnClickListener {

    private Context context;
    private View mView;
    private VideoView mVideoView;
    private ImageView mBigPlayBtn;
    private ImageView mPlayBtn;
    private ImageView mMuteImg;
    private SeekBar mPlayProgressBar;
    private TextView mPlayTime;
    private LinearLayout mControlPanel;
    private ProgressBar mLoading;

    private Uri mVideoUri = null;

    private Animation outAnima;
    private Animation inAnima;

    private int mVideoDuration;
    private int mCurrentProgress;

    private Runnable mUpdateTask;
    private Thread mUpdateThread;

    private final int UPDATE_PROGRESS = 0;
    private final int EXIT_CONTROL_PANEL = 1;
    private boolean stopThread = true;

    private Point screenSize = new Point();
    private boolean mIsFullScreen = false;

    private int mWidth;
    private int mHeigth;

    public SimpleVideoView(Context context) {
        super(context);
        init(context, null, 0);
    }

    public SimpleVideoView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public SimpleVideoView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_PROGRESS:
                    mPlayProgressBar.setProgress(mCurrentProgress);
                    setPlayTime(mCurrentProgress);
                    break;
                case EXIT_CONTROL_PANEL:
                    //perform exit animation
                    if (mControlPanel.getVisibility() != View.GONE) {
                        mControlPanel.startAnimation(outAnima);
                        mControlPanel.setVisibility(View.GONE);
                    }
                    break;
            }
        }
    };

    //Initialize the control
    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        this.context = context;
        mView = LayoutInflater.from(context).inflate(R.layout.layout_simple_video, this);
        mBigPlayBtn = (ImageView) mView.findViewById(R.id.big_play_button);
        mPlayBtn = (ImageView) mView.findViewById(R.id.play_button);
        mMuteImg = (ImageView) mView.findViewById(R.id.mute_un);
        mPlayProgressBar = (SeekBar) mView.findViewById(R.id.progress_bar);
        mLoading = (ProgressBar) mView.findViewById(R.id.loading);
        mPlayTime = (TextView) mView.findViewById(R.id.time);
        mControlPanel = (LinearLayout) mView.findViewById(R.id.control_panel);
        mVideoView = (VideoView) mView.findViewById(R.id.video_view);
        //get screen size
        ((Activity) context).getWindowManager().getDefaultDisplay().getSize(screenSize);
        //loading animation
        outAnima = AnimationUtils.loadAnimation(context, R.anim.exit_from_bottom);
        inAnima = AnimationUtils.loadAnimation(context, R.anim.enter_from_bottom);
        //The settings control panel is initially invisible
        mControlPanel.setVisibility(View.GONE);
        //Make the big play button visible
        mBigPlayBtn.setVisibility(View.VISIBLE);
        //Set up the media controller
//      mMediaController = new MediaController(context);
//      mMediaController.setVisibility(View.GONE);
//      mVideoView.setMediaController(mMediaController);
        mVideoView.setOnPreparedListener(new OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                //The video duration can only be obtained after the video is loaded
                initVideo();
            }
        });
        //Video playback completion listener
        mVideoView.setOnCompletionListener(new OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                mPlayBtn.setImageResource(R.mipmap.player);
                mVideoView.seekTo(0);
                mPlayProgressBar.setProgress(0);
                setPlayTime(0);
                stopThread = true;
                sendHideControlPanelMessage();
            }
        });

        mView.setOnClickListener(this);
    }

    //Initialize the video, set the video time and the maximum value of the progress bar
    private void initVideo() {
        mVideoView.start();
        mVideoView.pause();
        mLoading.setVisibility(GONE);
        //Initialize time and progress bar
        mVideoDuration = mVideoView.getDuration();//milliseconds
        int seconds = mVideoDuration / 1000;
        mPlayTime.setText("00:00/" +
                ((seconds / 60 > 9) ? (seconds / 60) : ("0" + seconds / 60)) + ":" +
                ((seconds % 60 > 9) ? (seconds % 60) : ("0" + seconds % 60)));
        mPlayProgressBar.setMax(mVideoDuration);
        mPlayProgressBar.setProgress(0);
        //Update progress bar and time tasks
        mUpdateTask = new Runnable() {
            @Override
            public void run() {
                while (!stopThread) {
                    mCurrentProgress = mVideoView.getCurrentPosition();
                    handler.sendEmptyMessage(UPDATE_PROGRESS);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        mBigPlayBtn.setOnClickListener(this);
        mPlayBtn.setOnClickListener(this);
        mMuteImg.setOnClickListener(this);
        //progress bar progress change listener
        mPlayProgressBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                handler.sendEmptyMessageDelayed(EXIT_CONTROL_PANEL, 3000);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                handler.removeMessages(EXIT_CONTROL_PANEL);
            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress,
                                          boolean fromUser) {
                if (fromUser) {
                    mVideoView.seekTo(progress);//set video
                    setPlayTime(progress);//set time
                }
            }
        });
        mWidth = this.getWidth();
        mHeigth = this.getHeight();
    }

    @Override
    public void onClick(View v) {
        if (v == mView) {
            if (mBigPlayBtn.getVisibility() == View.VISIBLE) {
                return;
            }
            if (mControlPanel.getVisibility() == View.VISIBLE) {
                //perform exit animation
                mControlPanel.startAnimation(outAnima);
                mControlPanel.setVisibility(View.GONE);
            } else {
                //Execute entry animation
                mControlPanel.startAnimation(inAnima);
                mControlPanel.setVisibility(View.VISIBLE);
                sendHideControlPanelMessage();
            }
        } else if (v.getId() == R.id.big_play_button) {//Play button in screen
            mBigPlayBtn.setVisibility(View.GONE);
            mVideoView.setBackground(null);
            if (!mVideoView.isPlaying()) {
                mVideoView.start();
                mPlayBtn.setImageResource(R.mipmap.pause);
                //Start update progress thread
                mUpdateThread = new Thread(mUpdateTask);
                stopThread = false;
                mUpdateThread.start();
            }
        } else if (v.getId() == R.id.play_button) {//play/pause button
            if (mVideoView.isPlaying()) {
                mVideoView.pause();
                mPlayBtn.setImageResource(R.mipmap.player);
            } else {
                if (mUpdateThread == null || !mUpdateThread.isAlive()) {
                    //Start update progress thread
                    mUpdateThread = new Thread(mUpdateTask);
                    stopThread = false;
                    mUpdateThread.start();
                }
                mVideoView.start();
                mPlayBtn.setImageResource(R.mipmap.pause);
            }
            sendHideControlPanelMessage();
        } else if (v.getId() == R.id.mute_un) {
            //sound and mute
            boolean tag1 = mMuteImg.getTag() == null ? false : (boolean) mMuteImg.getTag();
            mMuteImg.setImageResource(!tag1 ? R.mipmap.un_mute : R.mipmap.mute);
            mMuteImg.setTag(!tag1);
            AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, !tag1 ? 0 : 5, 0);
            sendHideControlPanelMessage();
        }
    }

    //set current time
    private void setPlayTime(int millisSecond) {
        int currentSecond = millisSecond / 1000;
        String currentTime = ((currentSecond / 60 > 9) ? (currentSecond / 60 + "") : ("0" + currentSecond / 60)) + ":" +
                ((currentSecond % 60 > 9) ? (currentSecond % 60 + "") : ("0" + currentSecond % 60));
        StringBuilder text = new StringBuilder(mPlayTime.getText().toString());
        text.replace(0, text.indexOf("/"), currentTime);
        mPlayTime.setText(text);
    }

    //Set the width and height of the control
    private void setSize() {
        ViewGroup.LayoutParams lp = this.getLayoutParams();
        if (mIsFullScreen) {
            lp.width = screenSize.y;
            lp.height = screenSize.x;
        } else {
            lp.width = mWidth;
            lp.height = mHeigth;
        }
        this.setLayoutParams(lp);
    }

    //Hide the control panel after two seconds
    private void sendHideControlPanelMessage() {
        handler.removeMessages(EXIT_CONTROL_PANEL);
        handler.sendEmptyMessageDelayed(EXIT_CONTROL_PANEL, 3000);
    }

    //set video path
    public void setVideoUri(Uri uri) {
        this.mVideoUri = uri;
        mVideoView.setVideoURI(mVideoUri);
    }

    //set video path
    public void setVideoUrl(String url) {
        mVideoView.setVideoPath(url);
    }

    //get video path
    public Uri getVideoUri() {
        return mVideoUri;
    }

    //Set the video splash screen
    public void setInitPicture(Drawable d) {
        mVideoView.setBackground(d);
    }

    //Suspend Video
    public void suspend() {
        if (mVideoView != null) {
            mVideoView.suspend();
        }
    }

    //Set video progress
    public void setVideoProgress(int millisSecond, boolean isPlaying) {
        mVideoView.setBackground(null);
        mBigPlayBtn.setVisibility(View.GONE);
        mPlayProgressBar.setProgress(millisSecond);
        setPlayTime(millisSecond);
        if (mUpdateThread == null || !mUpdateThread.isAlive()) {
            mUpdateThread = new Thread(mUpdateTask);
            stopThread = false;
            mUpdateThread.start();
        }
        mVideoView.seekTo(millisSecond);
        if (isPlaying) {
            mVideoView.start();
            mPlayBtn.setImageResource(R.mipmap.pause);
        } else {
            mVideoView.pause();
            mPlayBtn.setImageResource(R.mipmap.player);
        }
    }

    //Get video progress
    public int getVideoProgress() {
        return mVideoView.getCurrentPosition();
    }

    //Determine if a video is playing
    public boolean isPlaying() {
        return mVideoView.isPlaying();
    }

}

Step 5: Play Video

Play a video from a URL using the custom VideoView:

MainActivity.java

package zqiang94.github.io.videopalyer;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private SimpleVideoView mVideoView;

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

    private void initView() {
        mVideoView =  findViewById(R.id.simple_video);
        String url = "http://1255521334.vod2.myqcloud.com/ca2a1ebevodgzp1255521334/36ec9b975285890780567798103/hD68STre3sEA.mp4";
        mVideoView.setVideoUrl(url);
    }
}

Reference

Download full code here.
Follow code author here.

[Read Individually.](https://android.camposha.info/en/example/custom-videoview/)