From ffce2afa32d65eaff847084b9e132701fa951b85 Mon Sep 17 00:00:00 2001 From: Ekaterina Date: Fri, 15 Apr 2022 17:51:39 +0300 Subject: [PATCH] Internal-273 Feature DownloadManager --- file-download/.gitignore | 1 + file-download/build.gradle | 38 ++++++++ file-download/src/main/AndroidManifest.xml | 2 + .../file_download/DownloadFileManager.kt | 7 ++ .../file_download/DownloadFileManagerImpl.kt | 91 +++++++++++++++++++ 5 files changed, 139 insertions(+) create mode 100644 file-download/.gitignore create mode 100644 file-download/build.gradle create mode 100644 file-download/src/main/AndroidManifest.xml create mode 100644 file-download/src/main/java/ru/touchin/roboswag/file_download/DownloadFileManager.kt create mode 100644 file-download/src/main/java/ru/touchin/roboswag/file_download/DownloadFileManagerImpl.kt diff --git a/file-download/.gitignore b/file-download/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/file-download/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/file-download/build.gradle b/file-download/build.gradle new file mode 100644 index 0000000..99f41b5 --- /dev/null +++ b/file-download/build.gradle @@ -0,0 +1,38 @@ +apply from: "../android-configs/lib-config.gradle" + +dependencies { + + implementation 'androidx.core:core-ktx:1.7.0' + + implementation 'androidx.appcompat:appcompat:1.4.1' + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android") + + def coroutinesVersion = "1.3.7" + + constraints { + implementation("androidx.core:core-ktx") { + version { + require("1.2.0") + } + } + implementation("androidx.appcompat:appcompat") { + version { + require("1.0.2") + } + } + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core") { + version { + require(coroutinesVersion) + } + } + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android") { + version { + require(coroutinesVersion) + } + } + } + +} \ No newline at end of file diff --git a/file-download/src/main/AndroidManifest.xml b/file-download/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ea55625 --- /dev/null +++ b/file-download/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/file-download/src/main/java/ru/touchin/roboswag/file_download/DownloadFileManager.kt b/file-download/src/main/java/ru/touchin/roboswag/file_download/DownloadFileManager.kt new file mode 100644 index 0000000..7153608 --- /dev/null +++ b/file-download/src/main/java/ru/touchin/roboswag/file_download/DownloadFileManager.kt @@ -0,0 +1,7 @@ +package ru.touchin.roboswag.file_download + +interface DownloadFileManager { + + suspend fun download(fileName: String, fileUri: String, headers: Map = emptyMap()): String + +} \ No newline at end of file diff --git a/file-download/src/main/java/ru/touchin/roboswag/file_download/DownloadFileManagerImpl.kt b/file-download/src/main/java/ru/touchin/roboswag/file_download/DownloadFileManagerImpl.kt new file mode 100644 index 0000000..64f990a --- /dev/null +++ b/file-download/src/main/java/ru/touchin/roboswag/file_download/DownloadFileManagerImpl.kt @@ -0,0 +1,91 @@ +package ru.touchin.roboswag.file_download + +import android.annotation.SuppressLint +import android.app.DownloadManager +import android.content.Context +import android.content.Context.DOWNLOAD_SERVICE +import android.database.Cursor +import android.net.Uri +import android.os.Environment +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.withContext +import java.io.File + +class DownloadFileManagerImpl( + private val context: Context +) : DownloadFileManager { + + private val downloadManager: DownloadManager = context.getSystemService(DOWNLOAD_SERVICE) as DownloadManager + + override suspend fun download(fileName: String, fileUri: String, headers: Map): String { + val result = withContext(Dispatchers.Default) { + async { + downloadWithStatus(fileName, fileUri, headers) + } + } + return result.await() + + } + + private fun downloadWithStatus(fileName: String, fileUri: String, headers: Map): String { + var downloadId: Long + DownloadManager.Request(Uri.parse(fileUri)) + .apply { + setTitle(fileName) + setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName) + + headers.forEach { (key, value) -> + addRequestHeader(key, value) + } + + allowScanningByMediaScanner() + setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) + downloadId = downloadManager.enqueue(this) + } + return getStatus(downloadId, fileUri) + + } + + @SuppressLint("Range") + private fun getStatus(id: Long, url: String): String { + val query = DownloadManager.Query().setFilterById(id) + var status: Int + var downloading = true + do { + val cursor: Cursor = downloadManager.query(query) + cursor.moveToFirst() + val statusId = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) + if (isFinished(statusId)) { + downloading = false + } + status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) + cursor.close() + } while (downloading) + + return statusMessage(url, File(Environment.DIRECTORY_DOWNLOADS), status) + + } + + private fun statusMessage(url: String, directory: File, status: Int): String { + val 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 + + } + + private fun isFinished(status: Int): Boolean { + return status == DownloadManager.STATUS_SUCCESSFUL + || status == DownloadManager.STATUS_FAILED + + } + +}