DownloadWorker: Do cleanup on download failure/cancellation

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2023-10-29 18:13:16 +05:30
parent 01dee174bc
commit 932723d784

View File

@@ -27,16 +27,15 @@ import com.aurora.store.data.receiver.InstallReceiver
import com.aurora.store.util.NotificationUtil import com.aurora.store.util.NotificationUtil
import com.aurora.store.util.PathUtil import com.aurora.store.util.PathUtil
import com.google.gson.Gson import com.google.gson.Gson
import java.io.File
import java.net.URL
import java.nio.file.Path
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlin.io.path.Path import java.io.File
import kotlin.io.path.absolutePathString import java.net.URL
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.createDirectories import kotlin.io.path.createDirectories
import kotlin.io.path.deleteRecursively
import com.aurora.gplayapi.data.models.File as GPlayFile import com.aurora.gplayapi.data.models.File as GPlayFile
class DownloadWorker(private val appContext: Context, workerParams: WorkerParameters) : class DownloadWorker(private val appContext: Context, workerParams: WorkerParameters) :
@@ -66,6 +65,7 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame
} }
private lateinit var app: App private lateinit var app: App
private lateinit var notificationManager: NotificationManager
private var downloading = false private var downloading = false
private val TAG = DownloadWorker::class.java.simpleName private val TAG = DownloadWorker::class.java.simpleName
@@ -79,6 +79,9 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame
val purchaseHelper = PurchaseHelper(authData) val purchaseHelper = PurchaseHelper(authData)
.using(HttpClient.getPreferredClient(appContext)) .using(HttpClient.getPreferredClient(appContext))
notificationManager =
appContext.getSystemService(Service.NOTIFICATION_SERVICE) as NotificationManager
// Try to parse input data into a valid app // Try to parse input data into a valid app
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
try { try {
@@ -107,12 +110,25 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame
val requestList = getDownloadRequest(files) val requestList = getDownloadRequest(files)
requestList.forEach { request -> requestList.forEach { request ->
downloading = true downloading = true
downloadFile(request) runCatching { downloadFile(request) }
while (downloading && !isStopped) { .onSuccess { downloading = false }
.onFailure {
Log.e(TAG, "Failed to download ${app.packageName}", it)
downloading = false
onFailure()
return Result.failure()
}
while (downloading) {
delay(1000) delay(1000)
if (isStopped) {
onFailure()
break
}
} }
} }
if (!requestList.all { File(it.filePath).exists() }) return Result.failure()
// Mark download as completed // Mark download as completed
notifyStatus(DownloadStatus.COMPLETED) notifyStatus(DownloadStatus.COMPLETED)
Log.i(TAG, "Finished downloading ${app.packageName}") Log.i(TAG, "Finished downloading ${app.packageName}")
@@ -127,6 +143,14 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame
return Result.success() return Result.success()
} }
@OptIn(ExperimentalPathApi::class)
private fun onFailure() {
Log.i(TAG, "Cleaning up!")
PathUtil.getAppDownloadDir(appContext, app.packageName, app.versionCode)
.deleteRecursively()
notificationManager.cancel(notificationID)
}
private fun getDownloadRequest(files: List<GPlayFile>): List<Request> { private fun getDownloadRequest(files: List<GPlayFile>): List<Request> {
val downloadList = mutableListOf<Request>() val downloadList = mutableListOf<Request>()
files.filter { it.url.isNotBlank() }.forEach { files.filter { it.url.isNotBlank() }.forEach {
@@ -156,24 +180,23 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame
if (!File(request.filePath).exists()) { if (!File(request.filePath).exists()) {
Log.e(TAG, "Failed to find downloaded file at ${request.filePath}") Log.e(TAG, "Failed to find downloaded file at ${request.filePath}")
notifyStatus(DownloadStatus.FAILED) notifyStatus(DownloadStatus.FAILED)
downloading = false
return@withContext Result.failure() return@withContext Result.failure()
} }
downloading = false
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.filePath}!", exception)
requestFile.delete() requestFile.delete()
notifyStatus(DownloadStatus.FAILED) notifyStatus(DownloadStatus.FAILED)
downloading = false
return@withContext Result.failure() return@withContext Result.failure()
} }
} }
} }
private suspend fun onProgress(progress: Int) { private suspend fun onProgress(progress: Int) {
setProgress(Data.Builder().putInt(DOWNLOAD_PROGRESS, progress).build()) if (!isStopped) {
notifyStatus(DownloadStatus.DOWNLOADING, progress, notificationID) setProgress(Data.Builder().putInt(DOWNLOAD_PROGRESS, progress).build())
notifyStatus(DownloadStatus.DOWNLOADING, progress, notificationID)
}
} }
override suspend fun getForegroundInfo(): ForegroundInfo { override suspend fun getForegroundInfo(): ForegroundInfo {
@@ -192,8 +215,6 @@ class DownloadWorker(private val appContext: Context, workerParams: WorkerParame
} }
private fun notifyStatus(status: DownloadStatus, progress: Int = 100, dID: Int = -1) { private fun notifyStatus(status: DownloadStatus, progress: Int = 100, dID: Int = -1) {
val notificationManager =
appContext.getSystemService(Service.NOTIFICATION_SERVICE) as NotificationManager
val notification = val notification =
NotificationUtil.getDownloadNotification(appContext, app, status, progress, id) NotificationUtil.getDownloadNotification(appContext, app, status, progress, id)
notificationManager.notify(if (dID != -1) dID else app.packageName.hashCode(), notification) notificationManager.notify(if (dID != -1) dID else app.packageName.hashCode(), notification)