Skip to content
This repository has been archived by the owner on Jul 7, 2024. It is now read-only.

Fix the issue of apks not being downloaded completely #40

Merged
merged 3 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dev.beefers.vendetta.manager.domain.manager

import android.app.DownloadManager
import android.content.Context
import android.net.Uri
import android.os.Environment
import androidx.core.content.getSystemService
import io.ktor.client.HttpClient
import io.ktor.client.call.body
Expand All @@ -15,17 +17,10 @@ import java.io.InputStream
import java.io.OutputStream

class DownloadManager(
private val context: Context,
private val prefs: PreferenceManager
) {
private val httpClient = HttpClient {
install(HttpTimeout) {
socketTimeoutMillis = 1_000
connectTimeoutMillis = 10_000
requestTimeoutMillis = null
}
}

// Discord APK downloading
suspend fun downloadDiscordApk(version: String, out: File, onProgressUpdate: (Float) -> Unit): File =
download("${prefs.mirror.baseUrl}/tracker/download/$version/base", out, onProgressUpdate)

Expand All @@ -43,37 +38,52 @@ class DownloadManager(
download(
"https://github.com/vendetta-mod/VendettaManager/releases/latest/download/Manager.apk",
out
) { /* TODO: Update a progress bar in the update dialog */ }
) {
/* TODO: Update a progress bar in the update dialog */
}

suspend fun download(url: String, out: File, onProgressUpdate: (Float) -> Unit): File {
out.parentFile?.mkdirs()
httpClient.prepareGet(url).execute {
if(!out.exists()) out.createNewFile()
val channel = it.body<ByteReadChannel>()
val contentLength = it.contentLength()?.toInt() ?: 0
out.outputStream().use { os ->
channel.toInputStream().use { stream ->
println(stream.available())
stream.copyToWithProgress(os, bufferSize = 16384 * 2) { progress ->
onProgressUpdate(progress / contentLength.toFloat())
val request = DownloadManager.Request(Uri.parse(url))
.setTitle("Vendetta Manager")
.setDescription("Downloading ${out.name}...")
.setDestinationUri(Uri.fromFile(out))
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
.setAllowedOverMetered(true)
.setAllowedOverRoaming(true)

val downloadManager = context.getSystemService<DownloadManager>()
?: throw IllegalStateException("DownloadManager not available")

val downloadId = downloadManager.enqueue(request)

var lastProgress = 0L

while (true) {
val query = DownloadManager.Query().setFilterById(downloadId)
val cursor = downloadManager.query(query)

if (cursor.moveToFirst()) {
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
if (status == DownloadManager.STATUS_SUCCESSFUL) {
break
} else if (status == DownloadManager.STATUS_FAILED) {
// Handle download failure
break
} else {
val bytesDownloaded = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
val bytesTotal = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
val progress = if (bytesTotal > 0) bytesDownloaded * 100 / bytesTotal else 0

if (progress > lastProgress) {
onProgressUpdate(progress.toFloat() / 100f) // Corrected progress calculation
lastProgress = progress
}
}
}
cursor.close()
}
return out
}

private fun InputStream.copyToWithProgress(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SIZE, onProgressUpdate: (Long) -> Unit): Long {
var bytesCopied: Long = 0
val buffer = ByteArray(bufferSize)
var bytes = read(buffer)
while (bytes >= 0) {
out.write(buffer, 0, bytes)
bytesCopied += bytes
onProgressUpdate(bytesCopied)
bytes = read(buffer)
}
return bytesCopied
return out
}

}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.beefers.vendetta.manager.ui.widgets.installer

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
Expand All @@ -18,6 +19,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
Expand Down Expand Up @@ -99,7 +101,9 @@ fun StepGroupCard(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(16.dp),
) {
StepIcon(it.status, size = 18.dp, progress = it.progress)
val progress by animateFloatAsState(it.progress ?: 0f, label = "Progress")

StepIcon(it.status, size = 18.dp, progress = if(it.progress == null) null else progress)

Text(
text = stringResource(it.nameRes),
Expand Down