Home » Download Video from URL Android Kotlin

Download Video from URL Android Kotlin

download video from url android kotlin

In this post, I’m going to share with you, how to download video from URL in Android Kotlin. In this example, we going to build a simple UI that contains an EditText to get URL from the user and recycler view to display all the URLs entered by the User.

Download Video from URL – Android Kotlin

Let’s get started,

Let’s build our UI first. For that add the following dependencies into the build.gradle(app) file.

implementation "androidx.cardview:cardview:1.0.0"
implementation 'com.google.android.material:material:1.1.0'

And we also need the internet and write storage permissions so add these permissions in the AndroidManifest.xml file.

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

I have changed the base application theme to Theme.AppCompat.Light.NoActionBar inside res->values->styles.xml

Colors used in this project colors.xml.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#555EBA</color>
    <color name="colorPrimaryDark">#555EBA</color>
    <color name="colorAccent">#555EBA</color>
    <color name="lightAccent">#EAEDF0</color>
</resources>

Now let us create our main screen. For that, I have written the following XML code in activity_main.xml.

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">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fontFamily="@font/poppins_medium"
            android:text="Download"
            android:textColor="#000000"
            android:textSize="18sp"
            tools:layout_editor_absoluteX="16dp"
            tools:layout_editor_absoluteY="14dp" />
    </androidx.appcompat.widget.Toolbar>
    <TextView
        android:id="@+id/textViewUrlsAdded"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/poppins_medium"
        android:text="URLs Added"
        android:textColor="#000000"
        android:textSize="18sp"
        android:layout_marginStart="16dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/toolBar" />
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerViewUrls"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textViewUrlsAdded" />
</androidx.constraintlayout.widget.ConstraintLayout>

In the above code, we just have a toolbar and a recycler view. I have added recycler view to display the links which are entered by the user. So we have created a recycler item layout download_item.xml.

download_item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:backgroundTint="@color/lightAccent"
    android:layout_margin="8dp"
    app:cardElevation="0dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="16dp"
        android:layout_marginStart="12dp"
        android:layout_marginEnd="12dp"
        android:gravity="center_vertical">
        <TextView
            android:id="@+id/textViewUrl"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:fontFamily="@font/poppins"
            android:layout_weight="1"
            android:text=""
            android:paddingEnd="4dp"
            android:ellipsize="marquee"
            android:textColor="#000000"
            android:textSize="16sp"
            android:singleLine="true" />
        <ImageView
            android:id="@+id/imageViewOffline"
            android:layout_width="35dp"
            android:layout_height="35dp"
            android:src="@drawable/ic_offline"/>
    </LinearLayout>
</androidx.cardview.widget.CardView>

We have a plus icon on the top right corner. The user taps on that icon to add the URL. To add that icon create a menu XML file named main_menu.xml and add the following code.

main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/menuAddUrl"
        android:title="Add Url"
        android:icon="@drawable/ic_add"
        app:showAsAction="ifRoom"/>
</menu>

When the user taps on that plus icon we are going to show a custom alert dialog that contains an EditText and a button.  

Code for custom alert dialog get_url_layout.xml.

get_url_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">
        <EditText
            android:id="@+id/editTextUrl"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter Url"
            android:layout_marginTop="18dp"
            android:layout_marginStart="12dp"
            android:fontFamily="@font/poppins"
            android:layout_marginEnd="12dp"/>
        <Button
            android:id="@+id/buttonSave"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Save"
            android:fontFamily="@font/poppins_semibold"
            android:textColor="#FFFFFF"
            android:background="@color/colorPrimary"
            android:layout_marginTop="18dp"/>
</LinearLayout>

Now finally add the following code in MainActivity.kt file.

package com.example.videodownload
import android.app.DownloadManager
import android.content.Context
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.get_url_layout.*
class MainActivity : AppCompatActivity() {
    private val PERMISSION_REQUEST_CODE = 1234
    private val urlsAdded = ArrayList<String>()
    private val adapter = UrlsAddedAdapter(urlsAdded)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolBar)
        recyclerViewUrls.layoutManager = LinearLayoutManager(this)
        recyclerViewUrls.adapter = adapter
    }
    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.main_menu, menu)
        return true
    }
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            R.id.menuAddUrl -> {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                        //Permission Granted
                        getUrl()
                    } else {
                        ActivityCompat.requestPermissions(
                            this,
                            arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
                            PERMISSION_REQUEST_CODE
                        )
                    }
                } else {
                    //Less than M
                    getUrl()
                }
                true
            }
            else -> {
                return super.onOptionsItemSelected(item)
            }
        }
    }
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        when (requestCode) {
            PERMISSION_REQUEST_CODE -> {
                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    getUrl()
                } else {
                    showToast("Permission Denied...")
                }
            }
        }
    }
    private fun getUrl() {
        val builder = AlertDialog.Builder(this)
        builder.setTitle("Add Url")
        builder.setView(R.layout.get_url_layout)
        val alertDialog = builder.create()
        alertDialog.show()
        alertDialog.buttonSave.setOnClickListener {
            val url = alertDialog.editTextUrl.text.toString()
            if (url.isNotEmpty()) {
                alertDialog.dismiss()
                downloadFromUrl(url)
            }
        }
    }
    private fun downloadFromUrl(url: String) {
        try {
            urlsAdded.add(url)
            adapter.notifyDataSetChanged()
            val request = DownloadManager.Request(Uri.parse(url))
            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
            request.setTitle("Download")
            request.setDescription("Downloading Your File")
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
            request.setDestinationInExternalPublicDir(
                Environment.DIRECTORY_DOWNLOADS,
                System.currentTimeMillis().toString()
            )
            val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
            downloadManager.enqueue(request)
        } catch (exception: Exception) {
            showToast(exception.toString())
            if (urlsAdded.isNotEmpty()) {
                urlsAdded.removeAt(urlsAdded.size - 1)
                adapter.notifyDataSetChanged()
            }
        }
    }
    private fun showToast(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_LONG).show()
    }
}

In the above code, when the menu item with id menuAddUrl is selected. We are first going to check whether WRITE_EXTERNAL_STORAGE permission is granted or not.

If the permission is not granted, request permission or else call the getUrl() function to get the URL from the user. After getting the URL downloadFromUrl(url: String) function will be called. This function will download the video from the entered URL and store the video in internal storage.