Search code examples
androidkotlinbroadcastreceiverandroid-download-manager

How to hande different results of DownloadManager


What I need to do:
Download a file by URL using DownloadManager, and separetely handle successful download and error download.
What I tried:
I used BroadcastReceiver to catch the result of file download. I tried to use DownloadManager.ACTION_DOWNLOAD_COMPLETE as a marker but it fires not only when file is successfully downloaded but also when error occured and no file was downloaded.
So it seems like DownloadManager.ACTION_DOWNLOAD_COMPLETE reports only that attempt to download was made no matter with what result. Is there a way to catch only successful downloads?
my code:
fragment.kt

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
downloadCompleteReceiver = object : BroadcastReceiver(){
            override fun onReceive(context: Context?, intent: Intent?) {
            Snackbar.make(requireActivity().findViewById(android.R.id.content), getString(R.string.alert_files_successfully_downloaded), Snackbar.LENGTH_LONG).show()
            }
        }
        val filter = IntentFilter()
        filter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
        requireActivity().registerReceiver(downloadCompleteReceiver, filter)
}

Request:

fun downloadMediaFiles(listOfUrls: List<MediaDto>, activity: Activity, authToken:String) {
        if (isPermissionStorageProvided(activity)) {
            val manager = activity.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
            listOfUrls.forEach {
                val request = DownloadManager.Request(Uri.parse(it.url))
                request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
                request.setTitle(activity.getString(R.string.download_manager_title))
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                request.setDestinationInExternalPublicDir(
                    getDestinationDirectoryFromFileExtension(it.url),
                    "${System.currentTimeMillis()}"
                )
                request.addRequestHeader("authorization", authToken)
                manager.enqueue(request)
            }
        }
    }

SOLVED
What Rediska wrote + need also add this to my BroadcastReceiver object:

val referenceId = intent!!.getLongExtra(
                    DownloadManager.EXTRA_DOWNLOAD_ID, -1L
                )

and then pass this referenceId to getDownloadStatus as an arguement.
getDownloadStatus returns integer of 8 when successfull and 16 if failure, which I can further process.


Solution

  • This function will return the status of the download. See DownloadManager for values. It returns -1 if the download not found for given id.

    int getDownloadStatus(long id) {
        try {
             DownloadManager.Query query = new DownloadManager.Query();
             query.setFilterById(id);
             DownloadManager downloadManager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
             Cursor cursor = downloadManager.query(query);
             if (cursor.getCount() == 0) return -1;
             cursor.moveToFirst();
             return cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
        } catch(Exception ex) { return -1; }    
     }