Android Kotlin: Download Manager and Request Permission In Fragments

The old way of downloading an image or a file with URL is first to get the URL, create an InputStream instance, open the URL by using the HttpURLConnection class, then decode the bitmap or file and compress them and put the input stream instance to the decoded bitmap or file. This way, we need to put all the code into the doInBackground() method of AsyncTask class (will get exception otherwise), which is quite inconvenient. Therefore, there is the DownloadManager class.

DownloadManager for Android Developers

Here’s source code to implement the image downloading feature…

The download method

private fun downloadImage() {
  //TODO("not implemented")
  val destinationPath = "/wikiedu/images"
  val url = Uri.parse(courseUpload?.thumbUrl)
  val mDir = File(Environment.getExternalStorageDirectory(), "/wikiedu/images/")
  val downloadMgr: DownloadManager = context?.
  getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
  try {
       if (!mDir.exists()) {
        mDir.mkdir()
        Timber.d("Folder created at " + mDir)
       }
       val downloadRequest: DownloadManager.Request = DownloadManager.Request(url)

     /**Downloaded image will be stored in Downloads directory of a device if no destination dir is set **/
       downloadRequest.setAllowedNetworkTypes(DownloadManager
      .Request.NETWORK_WIFI or DownloadManager.Request.
       NETWORK_MOBILE).setAllowedOverMetered(true)            
         .setNotificationVisibility(DownloadManager.Request.
          VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
         .setAllowedOverMetered(true).setAllowedOverRoaming(false)
         .setTitle("Wikiedu Image Download")
         .setDescription("Downloading Image")
         .setDestinationInExternalPublicDir
         (destinationPath, mDir.absolutePath)

       downloadID = downloadMgr.enqueue(downloadRequest)
       onDownloadCompleteReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
          val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
          if (downloadID == id) {
            Toast.makeText(context, "Download complete!\n Image "
             + courseUpload?.fileName + " saved to "+ mDir,
             Toast.LENGTH_LONG).show()
            Timber.d("image saved to " + mDir)
          }
        }
      }
      //Register download broadcast receiver
       context?.registerReceiver(onDownloadCompleteReceiver,
                    
       IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))

  }catch (ie: IOException) {
       ie.stackTrace
  }
}
    ...

//Unregistered the download broadcast receiver in onDestroy() to clear download notifiaction after each download
override fun onDestroy() {
     super.onDestroy()
     context?.unregisterReceiver(onDownloadCompleteReceiver)
}

Set Request Permission:

private fun downloadImageWithPermission() {
  val permissionType = android.Manifest.permission.WRITE_EXTERNAL_STORAGE
  val isGranted = context?.applicationContext?.let {
     ContextCompat.checkSelfPermission(it,android.Manifest
     .permission.WRITE_EXTERNAL_STORAGE)
  }
  if (isGranted == PackageManager.PERMISSION_GRANTED) {
      downloadImage() //Call the download method
  } else {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
     //In a fragment, simply use requestPermissions() instead of ActivityCompat.requestPermission()    
       requestPermissions(arrayOf(permissionType),
       WRITE_EXTERNAL_STORAGE_RC)
     }
  }
}

Call onRequestPermissionResult() function

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
  super.onRequestPermissionsResult(requestCode, 
   permissions, grantResults)
  when (requestCode) {
    WRITE_EXTERNAL_STORAGE_RC -> {
   //If the Android version is higher than Marshmallow, request user permission
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
         grantResults.isEmpty() || grantResults[0] != 
           PackageManager.PERMISSION_GRANTED) {
        Timber.d("Permission denied by user")

    } else {
        downloadImage()//Call the download method again
        Timber.d("Permission granted by user")
    }
  }
 }
}

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.