Android DownloadManager Tutorial and Examples Show
In this session we explore the What is DownloadManager?The Why Download?Don’t underestimate the need for downloads and how complex it can get. The state of bandwith in the current era implies that we are still not able, at least in many parts of the world, to be able to obtain files we need on demand any time. Users don’t leave their internet on all time as it does cost money and drain the device’s battery. Hence being able to download files and store them locally is important. But this is not an easy task to implement properly. Especially doing it correctly and efficiently. Yet it is one of those tasks that can absolutely be shared among apps. There is no real need most of the time to re-invent the wheel while making http downloads. It makes sense to have one simple to use class that can do this efficiently and inform our app when the task is complete. Being able to download data is powerful way of enriching our apps as we can get files from the internet which our app can then use. If the user happens to remove the file, we can re-download it again. Common QuestionsHere are some of the questions to allow us understand the Which Types of Downloads are Handled by |
No. | Location | Link |
---|---|---|
1. | GitHub | Direct Download |
2. | GitHub | Browse |
3. | YouTube | Video Tutorial |
4. | YouTube | ProgrammingWizards TV Channel |
Example 2: Kotlin Android simple DownloadManager Example
A simple open source Kotlin downloadmanager example suitable for absolute beginners.
Step 1: Create Project
Start by creating an empty AndroidStudio project.
Step 2: Dependencies
No special third party library is needed for this project.
Step 3: Design Layout
Design you MainActivity layout by adding a textview in a ConstraintLayout as shown below:
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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Step 4: Write Code
Start by adding imports:
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.opengl.Visibility
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
Create MainActivity
by extending AppCompatActivity
:
class MainActivity : AppCompatActivity() {
Define a download ID:
var downloadid: Long = 0
Override onCreate()
callback:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Create an annonymouse BroadcastReceiver and inside it override the onReceive()
as follows:
val new = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadid) Log.d("DOWNLOAD", "DONE")
}
}
Create a Download Uri:
val uri = Uri.parse("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")
Initialize a DownloadRequest:
val request = DownloadManager.Request(uri).setDescription("DummyFile").setTitle("Dummy").setAllowedOverMetered(true).setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
Enqueue the Download:
val location = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadid = location.enqueue(request)
Register the BroadcastReceiver:
registerReceiver(new, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
Here is the full code:
MainActivity.kt
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.opengl.Visibility
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
class MainActivity : AppCompatActivity() {
var downloadid: Long = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val new = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
if (id == downloadid) Log.d("DOWNLOAD", "DONE")
}
}
val uri = Uri.parse("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")
val request = DownloadManager.Request(uri).setDescription("DummyFile").setTitle("Dummy").setAllowedOverMetered(true).setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
val location = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
downloadid = location.enqueue(request)
registerReceiver(new, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
}
}
Step 5: Add permissions
In your AndroidManifest
add the following permissions:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
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 3: Kotlin Android – Dynamic Download
In this example you learn how to download from any link. The link is provided at runtime via an EditText.
Step 1: Create Project
Start by creating an empty AndroidStudio project.
Step 2: Dependencies
No third party dependency is needed for this project.
Step 3: Design Layout
Add an EditText and Button in your mainactivity’s layout:
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">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:hint="Введите ссылку"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etLink"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/btnLoad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="load"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tilLink" />
</androidx.constraintlayout.widget.ConstraintLayout>
Step 4: Write Code
Start by adding imports to your MainActivity.kt
as follows:
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.view.Gravity
import android.widget.PopupMenu
import android.widget.Toast
import com.google.android.material.textfield.TextInputEditText
Create the Activity:
class MainActivity : AppCompatActivity() {
Define instance fields:
private var binding: ActivityMainBinding? = null
private var dm: DownloadManager? = null
Create an annonymouse BroadcastReceiver class and implement the onReceive()
method as follows:
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val action = intent?.action
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) {
Toast.makeText(context, "Download Completed", Toast.LENGTH_SHORT).show()
}
}
}
Setup event handlers:
private fun setupListeners() {
binding?.btnLoad?.setOnLongClickListener {
val popup = PopupMenu(this, it)
popup.inflate(R.menu.popup)
popup.show()
download()
false
}
}
Here is the function that downloads the item:
private fun download() {
dm?.enqueue(
DownloadManager.Request(Uri.parse(LINK_VIDEO))
.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_MOBILE or
DownloadManager.Request.NETWORK_WIFI
)
.setTitle("Download File.mp4")
.setDescription("This is very important file")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
// .setDestinationInExternalFilesDir(
// applicationContext , Environment.DIRECTORY_DOWNLOADS, "managerDownload24.mp4"
// )
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
"managerDownload24"
)
)
}
Unregister the BroadcastReceiver in the onCreate()
:
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(broadcastReceiver)
}
Here is the full code:
MainActivity.kt
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.view.Gravity
import android.widget.PopupMenu
import android.widget.Toast
import com.google.android.material.textfield.TextInputEditText
import ru.trinitydigital.downloadmanager.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private var binding: ActivityMainBinding? = null
private var dm: DownloadManager? = null
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val action = intent?.action
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) {
Toast.makeText(context, "Download Completed", Toast.LENGTH_SHORT).show()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding?.root)
registerReceiver(broadcastReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
dm = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
setupListeners()
}
private fun setupListeners() {
binding?.btnLoad?.setOnLongClickListener {
val popup = PopupMenu(this, it)
popup.inflate(R.menu.popup)
popup.show()
download()
false
}
}
private fun download() {
dm?.enqueue(
DownloadManager.Request(Uri.parse(LINK_VIDEO))
.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_MOBILE or
DownloadManager.Request.NETWORK_WIFI
)
.setTitle("Download File.mp4")
.setDescription("This is very important file")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
// .setDestinationInExternalFilesDir(
// applicationContext , Environment.DIRECTORY_DOWNLOADS, "managerDownload24.mp4"
// )
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
"managerDownload24"
)
)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(broadcastReceiver)
}
companion object {
private const val LINK_VIDEO = "https://images.unsplash.com/photo-1569974507005-6dc61f97fb5c?ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8anBnfGVufDB8fDB8&ixlib=rb-1.2.1&auto=format&fit=crop&w=900&q=60"
}
}
Android Manifest
In the AndroidManifest.xml
add the following permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
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 4: Kotlin DownloadManager with Runtime Permissions and Coroutines
Here is yet another DownloadManager example written in Kotlin. This utilizes Kotlin Coroutines. It also involves checking for necessary permissions at runtime before the download.
Step 1: Create Project
Start by creating an empty AndroidStudio
project.
Step 2: Dependencies
No third party dependency is used.
Step 3: Design Layout
Design a simple layout with a button and a textview:
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"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="12dp"
android:textColor="@color/black"
android:textSize="25sp" />
<Button
android:id="@+id/download_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="12dp"
android:text="DOWNLOAD PDF"
android:textColor="@android:color/white" />
</LinearLayout>
</RelativeLayout>
Step 4: Write Code
Start by adding imports:
import android.Manifest
import android.annotation.TargetApi
import android.app.DownloadManager
import android.content.Context
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
Extend the AppCompatActivity
:`
class MainActivity : AppCompatActivity() {
Then define a download URL as an instance field:
private var imageUrl = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
Override the onCreate()
:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
When the download button is clicked, before initiating download we check for permission:
download_btn.setOnClickListener {
// After API 23 (Marshmallow) and lower Android 10 you need to ask for permission first before save an image
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
askPermissions()
} else {
downloadImage(imageUrl)
}
}
If granted we initiate the download.
Here is the function to initiate download the image:
private fun downloadImage(url: String) {
val downloadManager = this.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadUri = Uri.parse(url)
val request = DownloadManager.Request(downloadUri).apply {
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(url.substring(url.lastIndexOf("/") + 1))
.setDescription("abc")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
url.substring(url.lastIndexOf("/") + 1)
)
}
//use when just to download the file with getting status
//downloadManager.enqueue(request)
val downloadId = downloadManager.enqueue(request)
val query = DownloadManager.Query().setFilterById(downloadId)
lifecycleScope.launchWhenStarted {
var lastMsg: String = ""
var downloading = true
while (downloading) {
val cursor: Cursor = downloadManager.query(query)
cursor.moveToFirst()
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false
}
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
val msg: String? = statusMessage(url, File(Environment.DIRECTORY_DOWNLOADS), status)
Log.e("DownloadManager", " Status is :$msg")
if (msg != lastMsg) {
withContext(Dispatchers.Main) {
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
text_view.text = msg
//Log.e("DownloadManager", "Status is :$msg")
}
lastMsg = msg ?: ""
}
cursor.close()
}
}
}
Here is the function that constructs and returns the Download status as a string that can be displayed to the user:
private fun statusMessage(url: String, directory: File, status: Int): String? {
var msg = ""
msg = when (status) {
DownloadManager.STATUS_FAILED -> "Download has been failed, please try again"
DownloadManager.STATUS_PAUSED -> "Paused"
DownloadManager.STATUS_PENDING -> "Pending"
DownloadManager.STATUS_RUNNING -> "Downloading..."
DownloadManager.STATUS_SUCCESSFUL -> "PDF downloaded successfully in $directory" + File.separator + url.substring(
url.lastIndexOf("/") + 1
)
else -> "There's nothing to download"
}
return msg
}
The following function will allow you to ask for the necessary permissions before we proceed with the download:
@TargetApi(Build.VERSION_CODES.M)
fun askPermissions() {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
AlertDialog.Builder(this)
.setTitle("Permission required")
.setMessage("Permission required to save photos from the Web.")
.setPositiveButton("Allow") { dialog, id ->
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
)
finish()
}
.setNegativeButton("Deny") { dialog, id -> dialog.cancel() }
.show()
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
)
// MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted
downloadImage(imageUrl)
}
}
Then handle the permission request resulytusing the following callback:
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE -> {
// If request is cancelled, the result arrays are empty.
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// permission was granted, yay!
// Download the Image
downloadImage(imageUrl)
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return
}
// Add other 'when' lines to check for other
// permissions this app might request.
else -> {
// Ignore all other requests.
}
}
}
Here is the full code:
MainActivity.kt
import android.Manifest
import android.annotation.TargetApi
import android.app.DownloadManager
import android.content.Context
import android.content.pm.PackageManager
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
class MainActivity : AppCompatActivity() {
private var imageUrl = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
//private var imageUrl = "http://10.0.2.2:8087/getFile"
//private var imageUrl = "https://www.orimi.com/pdf-test.pdf"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
download_btn.setOnClickListener {
//http://localhost:8087/getFile
//downloadImage("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")
//downloadImage("http://localhost:8087/getFile")
// After API 23 (Marshmallow) and lower Android 10 you need to ask for permission first before save an image
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
askPermissions()
} else {
downloadImage(imageUrl)
}
}
}
private fun downloadImage(url: String) {
//val directory = File(Environment.DIRECTORY_PICTURES)
// if (!directory.exists()) {
// directory.mkdirs()
// }
val downloadManager = this.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadUri = Uri.parse(url)
val request = DownloadManager.Request(downloadUri).apply {
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle(url.substring(url.lastIndexOf("/") + 1))
.setDescription("abc")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS,
url.substring(url.lastIndexOf("/") + 1)
)
}
//use when just to download the file with getting status
//downloadManager.enqueue(request)
val downloadId = downloadManager.enqueue(request)
val query = DownloadManager.Query().setFilterById(downloadId)
lifecycleScope.launchWhenStarted {
var lastMsg: String = ""
var downloading = true
while (downloading) {
val cursor: Cursor = downloadManager.query(query)
cursor.moveToFirst()
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false
}
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
val msg: String? = statusMessage(url, File(Environment.DIRECTORY_DOWNLOADS), status)
Log.e("DownloadManager", " Status is :$msg")
if (msg != lastMsg) {
withContext(Dispatchers.Main) {
// Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
text_view.text = msg
//Log.e("DownloadManager", "Status is :$msg")
}
lastMsg = msg ?: ""
}
cursor.close()
}
}
}
private fun statusMessage(url: String, directory: File, status: Int): String? {
var msg = ""
msg = when (status) {
DownloadManager.STATUS_FAILED -> "Download has been failed, please try again"
DownloadManager.STATUS_PAUSED -> "Paused"
DownloadManager.STATUS_PENDING -> "Pending"
DownloadManager.STATUS_RUNNING -> "Downloading..."
DownloadManager.STATUS_SUCCESSFUL -> "PDF downloaded successfully in $directory" + File.separator + url.substring(
url.lastIndexOf("/") + 1
)
else -> "There's nothing to download"
}
return msg
}
@TargetApi(Build.VERSION_CODES.M)
fun askPermissions() {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
AlertDialog.Builder(this)
.setTitle("Permission required")
.setMessage("Permission required to save photos from the Web.")
.setPositiveButton("Allow") { dialog, id ->
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
)
finish()
}
.setNegativeButton("Deny") { dialog, id -> dialog.cancel() }
.show()
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE
)
// MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted
downloadImage(imageUrl)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE -> {
// If request is cancelled, the result arrays are empty.
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// permission was granted, yay!
// Download the Image
downloadImage(imageUrl)
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return
}
// Add other 'when' lines to check for other
// permissions this app might request.
else -> {
// Ignore all other requests.
}
}
}
companion object {
private const val MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1
}
}
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 |