From 330762d86d6ad3667f88020d7b32734a1906a1c0 Mon Sep 17 00:00:00 2001 From: Rahul Patel Date: Thu, 27 Feb 2025 05:46:55 +0530 Subject: [PATCH] DownloadWorker: more work --- .../java/com/aurora/extensions/InputStream.kt | 5 +- .../aurora/store/data/work/DownloadWorker.kt | 83 ++++++++++--------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/aurora/extensions/InputStream.kt b/app/src/main/java/com/aurora/extensions/InputStream.kt index 69a444d45..ae8a65256 100644 --- a/app/src/main/java/com/aurora/extensions/InputStream.kt +++ b/app/src/main/java/com/aurora/extensions/InputStream.kt @@ -14,8 +14,7 @@ fun InputStream.copyTo(out: OutputStream, streamSize: Long): Flow var bytesCopied: Long = 0 val buffer = ByteArray(DEFAULT_BUFFER_SIZE) var bytes = read(buffer) - - var lastTotalBytesRead = 0L + var lastTotalBytesRead: Long = 0 var speed: Long = 0 @Suppress("KotlinConstantConditions") // False-positive for bytesCopied always being zero val timer = fixedRateTimer("timer", true, 0L, 1000) { @@ -26,6 +25,8 @@ fun InputStream.copyTo(out: OutputStream, streamSize: Long): Flow while (bytes >= 0) { out.write(buffer, 0, bytes) + out.flush() + bytesCopied += bytes // Emit stream progress in percentage emit(DownloadInfo((bytesCopied * 100 / streamSize).toInt(), bytes.toLong(), speed)) diff --git a/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt b/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt index f24faa931..1dd4416da 100644 --- a/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt +++ b/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt @@ -188,7 +188,12 @@ class DownloadWorker @AssistedInject constructor( ): Boolean = withContext(Dispatchers.IO) { for (file in files) { try { - downloadFile(file) + val success = downloadFile(file) + + if (!success) { + Log.w(TAG, "Download failed for $packageName") + return@withContext false + } if (isStopped) { Log.w(TAG, "Download cancelled for $packageName") @@ -288,51 +293,51 @@ class DownloadWorker @AssistedInject constructor( * Downloads the file from the given request. * Failed downloads aren't removed and persists as long as [CacheWorker] doesn't cleans them. * @param gFile A [GPlayFile] to download - * @return A [Result] indicating whether the file was downloaded or not. + * @return A [Boolean] indicating whether the file was downloaded or not. */ - private suspend fun downloadFile(gFile: GPlayFile): Result { + private suspend fun downloadFile(gFile: GPlayFile): Boolean = withContext(Dispatchers.IO) { Log.i(TAG, "Downloading ${gFile.name}") - return withContext(Dispatchers.IO) { - val file = PathUtil.getLocalFile(appContext, gFile, download) + val file = PathUtil.getLocalFile(appContext, gFile, download) - // If file exists and has integrity intact, no need to download again - if (file.exists() && verifyFile(gFile)) { - Log.i(TAG, "$file is already downloaded!") - downloadedBytes += file.length() - return@withContext Result.success() + // If file exists and has integrity intact, no need to download again + if (file.exists() && verifyFile(gFile)) { + Log.i(TAG, "$file is already downloaded!") + downloadedBytes += file.length() + return@withContext true + } + + val tmpFileSuffix = ".tmp" + val tmpFile = File(file.absolutePath + tmpFileSuffix) + + try { + // Download as a temporary file to avoid installing corrupted files + val isNewFile = tmpFile.createNewFile() + + val okHttpClient = httpClient as HttpClient + val headers = mutableMapOf() + + if (!isNewFile) { + Log.i(TAG, "$tmpFile has an unfinished download, resuming!") + downloadedBytes += tmpFile.length() + headers["Range"] = "bytes=${tmpFile.length()}-" } - try { - // Download as a temporary file to avoid installing corrupted files - val tmpFileSuffix = ".tmp" - val tmpFile = File(file.absolutePath + tmpFileSuffix) - val isNewFile = tmpFile.createNewFile() - - val okHttpClient = httpClient as HttpClient - val headers = mutableMapOf() - - if (!isNewFile) { - Log.i(TAG, "$tmpFile has an unfinished download, resuming!") - downloadedBytes += tmpFile.length() - headers["Range"] = "bytes=${tmpFile.length()}-" + okHttpClient.call(gFile.url, headers).body?.byteStream()?.use { input -> + FileOutputStream(tmpFile, !isNewFile).use { + input.copyTo(it, gFile.size).collect { info -> onProgress(info) } } - - okHttpClient.call(gFile.url, headers).body?.byteStream()?.use { input -> - FileOutputStream(tmpFile, !isNewFile).use { - input.copyTo(it, gFile.size).collect { p -> onProgress(p) } - } - } - - if (!tmpFile.renameTo(file)) { - throw Exception("Failed to remove .tmp extension from $tmpFile") - } - - return@withContext Result.success() - } catch (exception: Exception) { - Log.e(TAG, "Failed to download $file!", exception) - notifyStatus(DownloadStatus.FAILED) - return@withContext Result.failure() } + + if (!tmpFile.renameTo(file)) { + throw Exception("Failed to remove .tmp extension from $tmpFile") + } + + return@withContext true + } catch (exception: Exception) { + Log.e(TAG, "Failed to download $file!", exception) + tmpFile.delete() + notifyStatus(DownloadStatus.FAILED) + return@withContext true } }