Avoid accessing file's path when working with downloads

This will help us to use document tree in future to allow users custom download
directory.

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-03-27 19:52:41 +05:30
parent d15fd40296
commit 8abade8881
3 changed files with 21 additions and 20 deletions

View File

@@ -1,8 +1,10 @@
package com.aurora.store.data.model package com.aurora.store.data.model
import java.io.File
data class Request( data class Request(
val url: String, val url: String,
val filePath: String, val file: File,
val size: Long, val size: Long,
val sha1: String, val sha1: String,
val sha256: String val sha256: String

View File

@@ -167,7 +167,7 @@ class DownloadWorker @AssistedInject constructor(
} }
} }
if (!requestList.all { File(it.filePath).exists() }) return Result.failure() if (!requestList.all { it.file.exists() }) return Result.failure()
// Mark download as completed // Mark download as completed
onSuccess() onSuccess()
@@ -220,7 +220,7 @@ class DownloadWorker @AssistedInject constructor(
private fun getDownloadRequest(files: List<GPlayFile>, libPackageName: String?): List<Request> { private fun getDownloadRequest(files: List<GPlayFile>, libPackageName: String?): List<Request> {
val downloadList = mutableListOf<Request>() val downloadList = mutableListOf<Request>()
files.filter { it.url.isNotBlank() }.forEach { files.filter { it.url.isNotBlank() }.forEach {
val filePath = when (it.type) { val file = when (it.type) {
GPlayFile.FileType.BASE, GPlayFile.FileType.SPLIT -> { GPlayFile.FileType.BASE, GPlayFile.FileType.SPLIT -> {
PathUtil.getApkDownloadFile( PathUtil.getApkDownloadFile(
appContext, download.packageName, download.versionCode, it, libPackageName appContext, download.packageName, download.versionCode, it, libPackageName
@@ -231,26 +231,25 @@ class DownloadWorker @AssistedInject constructor(
PathUtil.getObbDownloadFile(download.packageName, it) PathUtil.getObbDownloadFile(download.packageName, it)
} }
} }
downloadList.add(Request(it.url, filePath, it.size, it.sha1, it.sha256)) downloadList.add(Request(it.url, file, it.size, it.sha1, it.sha256))
} }
return downloadList return downloadList
} }
private suspend fun downloadFile(request: Request): Result { private suspend fun downloadFile(request: Request): Result {
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
val requestFile = File(request.filePath)
val algorithm = if (request.sha256.isBlank()) Algorithm.SHA1 else Algorithm.SHA256 val algorithm = if (request.sha256.isBlank()) Algorithm.SHA1 else Algorithm.SHA256
val expectedSha = if (algorithm == Algorithm.SHA1) request.sha1 else request.sha256 val expectedSha = if (algorithm == Algorithm.SHA1) request.sha1 else request.sha256
// If file exists and sha matches the request, no need to download again // If file exists and sha matches the request, no need to download again
if (requestFile.exists() && validSha(requestFile, expectedSha, algorithm)) { if (request.file.exists() && validSha(request.file, expectedSha, algorithm)) {
Log.i(TAG, "$requestFile is already downloaded!") Log.i(TAG, "${request.file} is already downloaded!")
downloadedBytes += requestFile.length() downloadedBytes += request.file.length()
return@withContext Result.success() return@withContext Result.success()
} }
try { try {
val isNewFile = requestFile.createNewFile() val isNewFile = request.file.createNewFile()
val connection = if (proxy != null) { val connection = if (proxy != null) {
URL(request.url).openConnection(proxy) as HttpsURLConnection URL(request.url).openConnection(proxy) as HttpsURLConnection
} else { } else {
@@ -258,22 +257,22 @@ class DownloadWorker @AssistedInject constructor(
} }
if (!isNewFile) { if (!isNewFile) {
Log.i(TAG, "$requestFile has an unfinished download, resuming!") Log.i(TAG, "${request.file} has an unfinished download, resuming!")
downloadedBytes += requestFile.length() downloadedBytes += request.file.length()
connection.setRequestProperty("Range", "bytes=${requestFile.length()}-") connection.setRequestProperty("Range", "bytes=${request.file.length()}-")
} }
connection.inputStream.use { input -> connection.inputStream.use { input ->
FileOutputStream(requestFile, !isNewFile).use { FileOutputStream(request.file, !isNewFile).use {
input.copyTo(it, request.size).collectLatest { p -> onProgress(p) } input.copyTo(it, request.size).collectLatest { p -> onProgress(p) }
} }
} }
// Ensure downloaded file matches expected sha // Ensure downloaded file matches expected sha
assert(validSha(requestFile, expectedSha, algorithm)) assert(validSha(request.file, expectedSha, algorithm))
return@withContext Result.success() return@withContext Result.success()
} catch (exception: Exception) { } catch (exception: Exception) {
Log.e(TAG, "Failed to download ${request.filePath}!", exception) Log.e(TAG, "Failed to download ${request.file}!", exception)
notifyStatus(DownloadStatus.FAILED) notifyStatus(DownloadStatus.FAILED)
return@withContext Result.failure() return@withContext Result.failure()
} }

View File

@@ -50,7 +50,7 @@ object PathUtil {
sharedLibPackageName: String sharedLibPackageName: String
): File { ): File {
return File( return File(
getAppDownloadDir(context, packageName, versionCode).absolutePath, getAppDownloadDir(context, packageName, versionCode),
"$LIBRARIES/$sharedLibPackageName" "$LIBRARIES/$sharedLibPackageName"
) )
} }
@@ -61,13 +61,13 @@ object PathUtil {
versionCode: Int, versionCode: Int,
file: GPlayFile, file: GPlayFile,
sharedLibPackageName: String? = null sharedLibPackageName: String? = null
): String { ): File {
val downloadDir = if (!sharedLibPackageName.isNullOrBlank()) { val downloadDir = if (!sharedLibPackageName.isNullOrBlank()) {
getLibDownloadDir(context, packageName, versionCode, sharedLibPackageName) getLibDownloadDir(context, packageName, versionCode, sharedLibPackageName)
} else { } else {
File(getPackageDirectory(context, packageName), versionCode.toString()) File(getPackageDirectory(context, packageName), versionCode.toString())
} }
return File(downloadDir, file.name).absolutePath return File(downloadDir, file.name)
} }
fun getZipFile(context: Context, packageName: String, versionCode: Int): File { fun getZipFile(context: Context, packageName: String, versionCode: Int): File {
@@ -84,8 +84,8 @@ object PathUtil {
return File(Environment.getExternalStorageDirectory(), "/Android/obb/$packageName") return File(Environment.getExternalStorageDirectory(), "/Android/obb/$packageName")
} }
fun getObbDownloadFile(packageName: String, file: GPlayFile): String { fun getObbDownloadFile(packageName: String, file: GPlayFile): File {
return File(getObbDownloadDir(packageName), file.name).absolutePath return File(getObbDownloadDir(packageName), file.name)
} }
fun needsStorageManagerPerm(fileList: List<GPlayFile>): Boolean { fun needsStorageManagerPerm(fileList: List<GPlayFile>): Boolean {