Introduction
If your App only need a simple way to play videos on Android, then VideoView (android.widget.VideoView
) might just fit the bill. In this tutorial, we will learn how to use VideoView for video playback in our App.
Goals
At the end of the tutorial, you would have learned:
- How to use VideoView to play videos.
Tools Required
- Android Studio. The version used in this tutorial is Arctic Fox 2020.3.1 Patch 4.
Prerequisite Knowledge
- Intermediate Android.
- Storage Access Framework (SAF).
- ActivityResult APIs.
Project Setup
To follow along with the tutorial, perform the steps below:
-
Create a new Android project with the default Empty Activity.
-
Remove the default “Hello World!” TextView.
-
Add a new Button to ConstraintLayout.
-
Constraint it to the top, left and right of the screen.
-
Give the Button
64dp
margin from the top of the screen. -
Extract the Button’s
android:text
value to strings.xml with the value asPlay Video
. -
Your activity_main.xml should now look similar to this.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" tools:context=".MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="64dp" android:text="@string/button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
-
From the test device’s web browser, download the sample video from this project’s Github repository here. The sample video used here is the trailer of the short movie Sintel (© copyright Blender Foundation | durian.blender.org). Optionally, you can also drag and drop the video from your computer directly into the AVD.
Supported Media Formats
For Android to be able to playback a video file, the file format must either be supported by the Android system or the device vendor. The list of supported media formats by Android can be found here. To find out the supported Media MIME types on a device, we can use the various functions in the MediaCodecList class and the MediaCodecInfo class. For example, to list all supported(either encoding or decoding) MIME types on our AVD,
-
Add the function below to MainActivity.
private fun logCodecs(){ val codecList = MediaCodecList(ALL_CODECS) for (codecInfo in codecList.codecInfos){ for (mimeType in codecInfo.supportedTypes){ Log.d(TAG, mimeType) } } }
-
Add the top-level
TAG
constant.private const val TAG = "MAIN_ACTIVITY"
-
Call the function in
onCreate()
.logCodecs()
If you run your App now, it will log something similar to the content below (output has been formatted for readability).
audio/mp4a-latm
audio/3gpp
audio/amr-wb
audio/flac
audio/g711-alaw
audio/g711-mlaw
audio/mpeg
audio/opus
audio/raw
audio/vorbis
video/avc
video/x-vnd.on2.vp8
video/x-vnd.on2.vp9
video/av01
video/3gpp
video/hevc
video/mp4v-es
Preparing the VideoView
-
To play a video with a VideoView, first we will add a VideoView in activity_main.xml.
<VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/button" />
-
It looks a little bit better with some margin, so we will add
8dp
of margins to videoView.android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp"
-
We do not need to need to show the videoView until the video starts playing, so we will mark it as
invisible
at startup.android:visibility="invisible"
Open the Media file
Normally, only videos located under DCIM/
, Movies/
, and Pictures/
will be available in the MediaStore.Video table. Because our video file is located under /Downloads
, we will interact with it via the SAF.
-
Create the ActivityResultLauncher and an empty callback with the code below inside
onCreate()
.val openVideoLauncher = registerForActivityResult(OpenDocument()) { uri -> }
-
Retrieve the Button object.
//Gets the button reference val button = findViewById<Button>(R.id.button)
-
Bind the Button
onClickListener
to the file Picker, passing in an array of the video MIME types.button.setOnClickListener { val mimeTypes = arrayOf("video/mp4") //filters for mp4 videos openVideoLauncher.launch(mimeTypes) }
The VideoView object
The VideoView object provides convenient functions to make it super easy to play videos. To interact with it, follow the steps below.
-
Just above
openVideoLauncher
, retrieves the VideoView object.//Gets the videoView reference val videoView = findViewById<VideoView>(R.id.videoView)
-
Bind the code below to the
openVideoLauncher
callback. This code will set the URI object returned from ActivityResultLauncher as the source for the video, makes the VideoView visible, and then start the video.//Start the video now that we have the uri videoView.apply { setVideoURI(uri) //sets the video uri visibility = VISIBLE //makes videoView visible }.start()
Run the App
We are now ready to run our app. The workflow should be similar to the animation below.
Solution Code
MainActivity.kt
package com.example.daniwebandroidplayvideo
import android.media.MediaCodecList
import android.media.MediaCodecList.ALL_CODECS
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View.VISIBLE
import android.widget.Button
import android.widget.VideoView
import androidx.activity.result.contract.ActivityResultContracts.OpenDocument
private const val TAG = "MAIN_ACTIVITY"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
logCodecs()
//Gets the videoView reference
val videoView = findViewById<VideoView>(R.id.videoView)
val openVideoLauncher = registerForActivityResult(OpenDocument()) { uri ->
//Start the video now that we have the uri
videoView.apply {
setVideoURI(uri) //sets the video uri
visibility = VISIBLE //makes videoView visible
}.start()
}
//Gets the button reference
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
val mimeTypes = arrayOf("video/mp4") //filters for mp4 videos
openVideoLauncher.launch(mimeTypes)
}
}
private fun logCodecs(){
val codecList = MediaCodecList(ALL_CODECS)
for (codecInfo in codecList.codecInfos){
for (mimeType in codecInfo.supportedTypes){
Log.d(TAG, mimeType)
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="64dp"
android:text="@string/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/button" />
</androidx.constraintlayout.widget.ConstraintLayout>
strings.xml
<resources>
<string name="app_name">Daniweb Android Play Video</string>
<string name="button">Play Video</string>
</resources>
Summary
We have learned how to play a video using the VideoView. The full project code can be found at https://github.com/dmitrilc/DaniwebAndroidPlayVideoVideoView