Introduction
In the world of mobile applications, video playback is a common requirement. Whether it’s for streaming content, displaying tutorials, or showcasing a product, integrating video functionality enhances user experience. In Android, the VideoView class simplifies the process of implementing a video player, while the MediaController class allows you to easily manage playback controls like play, pause, and seek.
This tutorial will guide you through creating a simple video player using Kotlin. By the end, you'll understand how to utilize these classes effectively and build a functional video player for your Android app.
Concept Explanation
What is VideoView?
The VideoView class is part of the Android framework that allows you to play video files in your application. Imagine it as a window through which your app can show moving images. When you want to include a video in your app, the VideoView is the go-to component.
Why Use MediaController?
The MediaController class provides a user interface for controlling video playback. Think of it as a remote control for your video player. Without it, users would have to interact with the video in a very limited manner, which could lead to frustration. With a MediaController, you can easily provide play, pause, rewind, and fast-forward options.
When to Use These Classes
You would typically use VideoView and MediaController in scenarios like:
- Streaming video content from the internet.
- Playing local video files stored on the device.
- Displaying video tutorials or promotional content in your app.
Syntax Section
Here’s a brief overview of the basic syntax for using VideoView and MediaController:
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val videoView = findViewById<VideoView>(R.id.videoView)
val mediaController = MediaController(this)
// Set up the MediaController
mediaController.setAnchorView(videoView)
// Specify the video file's URI
val uri: Uri = Uri.parse("android.resource://" + packageName + "/" + R.raw.video)
// Set the URI and MediaController
videoView.setMediaController(mediaController)
videoView.setVideoURI(uri)
// Start playback
videoView.requestFocus()
videoView.start()
}
}
Explanation of the Syntax Parts
- VideoView: This is where the video is displayed.
- MediaController: This provides playback controls.
- setAnchorView: This method attaches the MediaController to the VideoView, allowing it to control playback.
- setVideoURI: This method sets the source of the video.
- start: This method begins video playback.
Examples
Example 1: Playing a Local Video File
Let’s create a simple video player that plays a local video file stored in the "res/raw" directory.
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">
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
package com.example.videoplayer
import android.net.Uri
import android.os.Bundle
import android.widget.MediaController
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val videoView = findViewById<VideoView>(R.id.videoView)
val mediaController = MediaController(this)
mediaController.setAnchorView(videoView)
// Specify the location of the video file
val uri: Uri = Uri.parse("android.resource://${packageName}/${R.raw.sample_video}")
// Set the MediaController and video URI
videoView.setMediaController(mediaController)
videoView.setVideoURI(uri)
videoView.requestFocus()
videoView.start()
}
}
Expected Output:
When you run the app, the video located in res/raw/sample_video.mp4 will start playing with controls for play, pause, and seek.
---
Example 2: Playing Video from External Storage
In this example, let's play a video file stored on the device’s external storage.
MainActivity.kt
package com.example.videoplayer
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.widget.MediaController
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val videoView = findViewById<VideoView>(R.id.videoView)
val mediaController = MediaController(this)
mediaController.setAnchorView(videoView)
// Specify the location of the video file
val uri: Uri = Uri.parse(Environment.getExternalStorageDirectory().absolutePath + "/Movies/sample_video.mp4")
// Set the MediaController and video URI
videoView.setMediaController(mediaController)
videoView.setVideoURI(uri)
videoView.requestFocus()
videoView.start()
}
}
Expected Output:
Running this code will play the video file located at /sdcard/Movies/sample_video.mp4.
---
Example 3: Handling Video Playback States
This example will demonstrate how to handle different video playback states such as pause, resume, and stop.
MainActivity.kt
package com.example.videoplayer
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.widget.Button
import android.widget.MediaController
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private lateinit var videoView: VideoView
private lateinit var mediaController: MediaController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
videoView = findViewById(R.id.videoView)
mediaController = MediaController(this)
mediaController.setAnchorView(videoView)
val uri: Uri = Uri.parse(Environment.getExternalStorageDirectory().absolutePath + "/Movies/sample_video.mp4")
videoView.setMediaController(mediaController)
videoView.setVideoURI(uri)
videoView.requestFocus()
videoView.start()
findViewById<Button>(R.id.btnPause).setOnClickListener {
videoView.pause()
}
findViewById<Button>(R.id.btnResume).setOnClickListener {
videoView.start()
}
findViewById<Button>(R.id.btnStop).setOnClickListener {
videoView.stopPlayback()
}
}
}
activity_main.xml
<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">
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toTopOf="@+id/buttonLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/buttonLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/btnPause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pause" />
<Button
android:id="@+id/btnResume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Resume" />
<Button
android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Expected Output:
This example provides buttons to pause, resume, and stop playback of the video, enhancing the user control over video playback.
Common Mistakes
Using Incorrect URI
One common mistake is providing an incorrect URI for the video file. For instance, if you specify a non-existent file path, the video won’t play, and you might encounter a FileNotFoundException.
Incorrect Example:
val uri: Uri = Uri.parse("android.resource://${packageName}/non_existent_video.mp4")
Not Requesting Permissions
When accessing videos from external storage, you must ensure that your app has the appropriate permissions. If you forget to add the READEXTERNALSTORAGE permission in the AndroidManifest.xml, the app will crash when trying to access the file.
Correct Permissions:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Best Practices
- Handle Permissions: Always check and request runtime permissions for accessing external storage in Android 6.0 (API level 23) and above.
- Check Video Format: Ensure the video format is supported. Android supports common formats like MP4, 3GP, and MKV.
- Optimize Playback: Use lower resolution videos for better performance on lower-end devices.
- Error Handling: Implement error handling to manage playback failures gracefully without crashing the app.
Practice Exercises
- Custom Video Player UI: Create a video player that includes a custom UI with buttons for play, pause, and stop.
- Hint: Use
ImageButtonfor custom buttons instead of the default MediaController.
- Video Selection: Build an activity that allows users to select a video from their device storage and play it.
- Hint: Use an
Intentto access the device's file picker.
- Playback State Management: Extend the previous examples to save and restore the video playback state when the app is paused or resumed.
- Hint: Use
onPauseandonResumelifecycle methods to save and restore the current playback position.
By completing these exercises, you'll solidify your understanding of video playback in Android using Kotlin. Happy coding!