Downloaded (large?) files are truncated
This commit is contained in:
parent
19f16c9e56
commit
80e8cd4191
@ -58,6 +58,7 @@ internal class DefaultFileService @Inject constructor(
|
||||
/**
|
||||
* Download file in the cache folder, and eventually decrypt it
|
||||
* TODO implement clear file, to delete "MF"
|
||||
* TODO looks like files are copied 3 times
|
||||
*/
|
||||
override fun downloadFile(downloadMode: FileService.DownloadMode,
|
||||
id: String,
|
||||
@ -87,20 +88,30 @@ internal class DefaultFileService @Inject constructor(
|
||||
return@flatMap Try.Failure(e)
|
||||
}
|
||||
|
||||
var inputStream = response.body?.byteStream()
|
||||
Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${inputStream?.available()}")
|
||||
|
||||
if (!response.isSuccessful || inputStream == null) {
|
||||
if (!response.isSuccessful) {
|
||||
return@flatMap Try.Failure(IOException())
|
||||
}
|
||||
|
||||
val source = response.body?.source()
|
||||
?: return@flatMap Try.Failure(IOException())
|
||||
|
||||
Timber.v("Response size ${response.body?.contentLength()} - Stream available: ${!source.exhausted()}")
|
||||
|
||||
if (elementToDecrypt != null) {
|
||||
Timber.v("## decrypt file")
|
||||
inputStream = MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt)
|
||||
?: return@flatMap Try.Failure(IllegalStateException("Decryption error"))
|
||||
val decryptedStream = MXEncryptedAttachments.decryptAttachment(source.inputStream(), elementToDecrypt)
|
||||
response.close()
|
||||
if (decryptedStream == null) {
|
||||
return@flatMap Try.Failure(IllegalStateException("Decryption error"))
|
||||
} else {
|
||||
decryptedStream.use {
|
||||
writeToFile(decryptedStream, destFile)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeToFile(source.inputStream(), destFile)
|
||||
response.close()
|
||||
}
|
||||
|
||||
writeToFile(inputStream, destFile)
|
||||
}
|
||||
|
||||
Try.just(copyFile(destFile, downloadMode))
|
||||
|
@ -17,10 +17,8 @@
|
||||
package im.vector.matrix.android.internal.util
|
||||
|
||||
import androidx.annotation.WorkerThread
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import okio.source
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
|
||||
/**
|
||||
@ -28,9 +26,7 @@ import java.io.InputStream
|
||||
*/
|
||||
@WorkerThread
|
||||
fun writeToFile(inputStream: InputStream, outputFile: File) {
|
||||
inputStream.source().buffer().use { input ->
|
||||
outputFile.sink().buffer().use { output ->
|
||||
output.writeAll(input)
|
||||
}
|
||||
FileOutputStream(outputFile).use {
|
||||
inputStream.copyTo(it)
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,14 @@ package im.vector.riotx.core.files
|
||||
import android.app.DownloadManager
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.MediaStore
|
||||
import androidx.annotation.WorkerThread
|
||||
import arrow.core.Try
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import okio.source
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
|
||||
@ -56,7 +58,7 @@ fun addEntryToDownloadManager(context: Context,
|
||||
file: File,
|
||||
mimeType: String,
|
||||
title: String = file.name,
|
||||
description: String = file.name) {
|
||||
description: String = file.name) : Uri? {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
val contentValues = ContentValues().apply {
|
||||
@ -65,17 +67,31 @@ fun addEntryToDownloadManager(context: Context,
|
||||
put(MediaStore.Downloads.MIME_TYPE, mimeType)
|
||||
put(MediaStore.Downloads.SIZE, file.length())
|
||||
}
|
||||
context.contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)?.let { uri ->
|
||||
context.contentResolver.openOutputStream(uri)?.use { outputStream ->
|
||||
outputStream.sink().buffer().write(file.inputStream().use { it.readBytes() })
|
||||
return context.contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues)
|
||||
?.let { uri ->
|
||||
Timber.v("## addEntryToDownloadManager(): $uri")
|
||||
val source = file.inputStream().source().buffer()
|
||||
context.contentResolver.openOutputStream(uri)?.sink()?.buffer()?.let { sink ->
|
||||
source.use { input ->
|
||||
sink.use { output ->
|
||||
output.writeAll(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
uri
|
||||
} ?: run {
|
||||
Timber.v("## addEntryToDownloadManager(): context.contentResolver.insert failed")
|
||||
|
||||
null
|
||||
}
|
||||
} else {
|
||||
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager?
|
||||
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as? DownloadManager
|
||||
@Suppress("DEPRECATION")
|
||||
downloadManager?.addCompletedDownload(title, description, true, mimeType, file.absolutePath, file.length(), true)
|
||||
return null
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## addEntryToDownloadManager(): Exception")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
@ -167,6 +167,7 @@ import im.vector.riotx.features.invite.VectorInviteView
|
||||
import im.vector.riotx.features.media.ImageContentRenderer
|
||||
import im.vector.riotx.features.media.VideoContentRenderer
|
||||
import im.vector.riotx.features.notifications.NotificationDrawerManager
|
||||
import im.vector.riotx.features.notifications.NotificationUtils
|
||||
import im.vector.riotx.features.permalink.NavigationInterceptor
|
||||
import im.vector.riotx.features.permalink.PermalinkHandler
|
||||
import im.vector.riotx.features.reactions.EmojiReactionPickerActivity
|
||||
@ -209,6 +210,7 @@ class RoomDetailFragment @Inject constructor(
|
||||
private val eventHtmlRenderer: EventHtmlRenderer,
|
||||
private val vectorPreferences: VectorPreferences,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val notificationUtils: NotificationUtils,
|
||||
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager) :
|
||||
VectorBaseFragment(),
|
||||
TimelineEventController.Callback,
|
||||
@ -486,8 +488,19 @@ class RoomDetailFragment @Inject constructor(
|
||||
if (action.throwable != null) {
|
||||
activity.toast(errorFormatter.toHumanReadable(action.throwable))
|
||||
} else if (action.file != null) {
|
||||
activity.toast(getString(R.string.downloaded_file, action.file.path))
|
||||
addEntryToDownloadManager(activity, action.file, action.mimeType)
|
||||
addEntryToDownloadManager(activity, action.file, action.mimeType)?.let {
|
||||
// This is a temporary solution to help users find downloaded files
|
||||
// there is a better way to do that
|
||||
// On android Q+ this method returns the file URI, on older
|
||||
// it returns null, and the download manager handles the notification
|
||||
notificationUtils.buildDownloadFileNotification(
|
||||
it,
|
||||
action.file.name ?: "file",
|
||||
action.mimeType
|
||||
).let { notification ->
|
||||
notificationUtils.showNotificationMessage("DL", action.file.absolutePath.hashCode(), notification)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,6 +480,26 @@ class NotificationUtils @Inject constructor(private val context: Context,
|
||||
.build()
|
||||
}
|
||||
|
||||
fun buildDownloadFileNotification(uri: Uri, fileName: String, mimeType: String): Notification {
|
||||
return NotificationCompat.Builder(context, SILENT_NOTIFICATION_CHANNEL_ID)
|
||||
.setGroup(stringProvider.getString(R.string.app_name))
|
||||
.setSmallIcon(R.drawable.ic_download)
|
||||
.setContentText(stringProvider.getString(R.string.downloaded_file, fileName))
|
||||
.setAutoCancel(true)
|
||||
.apply {
|
||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
||||
setDataAndType(uri, mimeType)
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
PendingIntent.getActivity(
|
||||
context, System.currentTimeMillis().toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT
|
||||
).let {
|
||||
setContentIntent(it)
|
||||
}
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a notification for a Room
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user