Код: Выделить всё
fun download(
dest: File,
url: String,
filename: String,
onPreExecute: () -> Unit = {},
onPostExecute: (Any) -> Unit = {},
onProgress: (DownloadState) -> Unit = {},
): Job {
return appScope.executeAsyncTask(
onPreExecute = onPreExecute,
onPostExecute = onPostExecute,
onProgress = onProgress,
doInBackground = { reportProgress: suspend (progress: DownloadState) -> Unit ->
try {
val httpUrl = URL(url)
val connection = httpUrl.openConnection()
connection.connect()
val totalBytes = connection.contentLengthLong
httpUrl.openStream().use { ins ->
BufferedInputStream(ins).use { bis ->
FileOutputStream(File(dest, filename)).use { fos ->
var bytesRead: Int
var totalBytesRead = 0L
val buffer = ByteArray(4096)
// Downloading started
val ds = DownloadState(
downloading = true,
fileSizeBytes = totalBytes
)
while (
bis.read(
/* b = */ buffer,
/* off = */0,
/* len = */buffer.size
).also { bytesRead = it } != -1
) {
totalBytesRead += bytesRead
// Report download progress
reportProgress(
ds.copy(
bytesDownloaded = totalBytesRead,
progress = (totalBytesRead / totalBytes.toFloat())
)
)
fos.write(buffer, 0, bytesRead)
}
// Downloading finished
reportProgress(ds.copy(downloading = false))
}
}
}
} catch (e: Exception) {
e.printStackTrace()
Log.e(TAG, e.message.toString())
reportProgress(DownloadState(error = e, downloading = false))
throw e
}
}
)
}
Код: Выделить всё
private fun download(directory: File) {
viewModelScope.launch {
try {
val audios = listOf(/* Audio(...) */)
if (isExternalStorageWritable()) {
audios.forEachIndexed { i, s ->
val count = i + 1
val id = s.id
val done = count == audios.size
val filename = audio.getFilename(id)
val dest = File(directory, audio.getDirectory())
if (!dest.exists()) dest.mkdirs()
// If file already exists skip it
if (File(dest, filename).exists()) {
_uiState.update {
val audioCount = it.audioCount + 1
it.copy(
audioCount = audioCount,
syncCompleted = done,
audioDownloadDone = done,
)
}
return@forEach
}
downloadClient.download(
dest = dest,
filename = filename,
url = audio.url,
onPostExecute = {
_uiState.update {
val audioCount = it.audioCount + 1
it.copy(
audioCount = audioCount,
syncCompleted = done,
audioDownloadDone = done,
)
}
}
)
}
}
} catch (e: Exception) {
_uiState.update {
it.copy(
syncCompleted = true,
audioDownloadErred = true,
)
}
}
}
}
Имейте в виду, что мне также необходимо обновить пользовательский интерфейс с помощью прогресс загрузки.
Не стесняйтесь предлагать другие варианты/библиотеки с кодом, которые помогут обойти эту проблему.
Подробнее здесь: https://stackoverflow.com/questions/787 ... st-of-urls
Мобильная версия