mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-25 10:37:20 +00:00
downloadattachmentjob implementation
This commit is contained in:
parent
3a9304098b
commit
842f00ee54
@ -2,14 +2,18 @@ package org.thoughtcrime.securesms.attachments
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.session.libsession.database.MessageDataProvider
|
import org.session.libsession.database.MessageDataProvider
|
||||||
|
import org.session.libsession.events.AttachmentProgressEvent
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentState
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentState
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.SessionServiceAttachmentPointer
|
import org.session.libsession.messaging.sending_receiving.attachments.SessionServiceAttachmentPointer
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.SessionServiceAttachmentStream
|
import org.session.libsession.messaging.sending_receiving.attachments.SessionServiceAttachmentStream
|
||||||
import org.session.libsignal.libsignal.util.guava.Optional
|
import org.session.libsignal.libsignal.util.guava.Optional
|
||||||
|
import org.session.libsignal.service.api.messages.SignalServiceAttachment
|
||||||
import org.thoughtcrime.securesms.database.Database
|
import org.thoughtcrime.securesms.database.Database
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||||
|
import org.thoughtcrime.securesms.events.PartProgressEvent
|
||||||
import org.thoughtcrime.securesms.jobs.AttachmentUploadJob
|
import org.thoughtcrime.securesms.jobs.AttachmentUploadJob
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil
|
import org.thoughtcrime.securesms.util.MediaUtil
|
||||||
@ -58,7 +62,9 @@ fun DatabaseAttachment.toAttachmentPointer(): SessionServiceAttachmentPointer {
|
|||||||
|
|
||||||
fun DatabaseAttachment.toAttachmentStream(context: Context): SessionServiceAttachmentStream {
|
fun DatabaseAttachment.toAttachmentStream(context: Context): SessionServiceAttachmentStream {
|
||||||
val stream = PartAuthority.getAttachmentStream(context, this.dataUri!!)
|
val stream = PartAuthority.getAttachmentStream(context, this.dataUri!!)
|
||||||
var attachmentStream = SessionServiceAttachmentStream(stream, this.contentType, this.size, Optional.fromNullable(this.fileName), this.isVoiceNote, Optional.absent(), this.width, this.height, Optional.fromNullable(this.caption), null)
|
val listener = SignalServiceAttachment.ProgressListener { total: Long, progress: Long -> EventBus.getDefault().postSticky(PartProgressEvent(this, total, progress))}
|
||||||
|
|
||||||
|
var attachmentStream = SessionServiceAttachmentStream(stream, this.contentType, this.size, Optional.fromNullable(this.fileName), this.isVoiceNote, Optional.absent(), this.width, this.height, Optional.fromNullable(this.caption), listener)
|
||||||
attachmentStream.attachmentId = this.attachmentId.rowId
|
attachmentStream.attachmentId = this.attachmentId.rowId
|
||||||
attachmentStream.isAudio = MediaUtil.isAudio(this)
|
attachmentStream.isAudio = MediaUtil.isAudio(this)
|
||||||
attachmentStream.isGif = MediaUtil.isGif(this)
|
attachmentStream.isGif = MediaUtil.isGif(this)
|
||||||
@ -66,12 +72,10 @@ fun DatabaseAttachment.toAttachmentStream(context: Context): SessionServiceAttac
|
|||||||
attachmentStream.isImage = MediaUtil.isImage(this)
|
attachmentStream.isImage = MediaUtil.isImage(this)
|
||||||
|
|
||||||
attachmentStream.key = ByteString.copyFrom(this.key?.toByteArray())
|
attachmentStream.key = ByteString.copyFrom(this.key?.toByteArray())
|
||||||
attachmentStream.digest = this.digest
|
attachmentStream.digest = Optional.fromNullable(this.digest)
|
||||||
|
|
||||||
attachmentStream.url = this.url
|
attachmentStream.url = this.url
|
||||||
|
|
||||||
//TODO attachmentStream.listener
|
|
||||||
|
|
||||||
return attachmentStream
|
return attachmentStream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package org.session.libsession.events
|
|
||||||
|
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.SessionServiceAttachment
|
|
||||||
|
|
||||||
class AttachmentProgressEvent(attachment: SessionServiceAttachment, total: Long, progress: Long) {
|
|
||||||
}
|
|
@ -1,14 +1,10 @@
|
|||||||
package org.session.libsession.messaging.jobs
|
package org.session.libsession.messaging.jobs
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import org.session.libsession.events.AttachmentProgressEvent
|
|
||||||
import org.session.libsession.messaging.MessagingConfiguration
|
import org.session.libsession.messaging.MessagingConfiguration
|
||||||
import org.session.libsession.messaging.fileserver.FileServerAPI
|
import org.session.libsession.messaging.fileserver.FileServerAPI
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentState
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentState
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.SessionServiceAttachment
|
|
||||||
import org.session.libsession.messaging.utilities.DotNetAPI
|
import org.session.libsession.messaging.utilities.DotNetAPI
|
||||||
import org.session.libsignal.service.api.crypto.AttachmentCipherInputStream
|
import org.session.libsignal.service.api.crypto.AttachmentCipherInputStream
|
||||||
import org.session.libsignal.service.api.messages.SignalServiceAttachment
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
|
|
||||||
@ -33,7 +29,7 @@ class AttachmentDownloadJob(val attachmentID: Long, val tsIncomingMessageID: Lon
|
|||||||
|
|
||||||
override fun execute() {
|
override fun execute() {
|
||||||
val messageDataProvider = MessagingConfiguration.shared.messageDataProvider
|
val messageDataProvider = MessagingConfiguration.shared.messageDataProvider
|
||||||
val attachmentPointer = messageDataProvider.getAttachmentPointer(attachmentID) ?: return handleFailure(Error.NoAttachment)
|
val attachmentStream = messageDataProvider.getAttachmentStream(attachmentID) ?: return handleFailure(Error.NoAttachment)
|
||||||
messageDataProvider.setAttachmentState(AttachmentState.STARTED, attachmentID, this.tsIncomingMessageID)
|
messageDataProvider.setAttachmentState(AttachmentState.STARTED, attachmentID, this.tsIncomingMessageID)
|
||||||
val tempFile = createTempFile()
|
val tempFile = createTempFile()
|
||||||
val handleFailure: (java.lang.Exception) -> Unit = { exception ->
|
val handleFailure: (java.lang.Exception) -> Unit = { exception ->
|
||||||
@ -51,19 +47,21 @@ class AttachmentDownloadJob(val attachmentID: Long, val tsIncomingMessageID: Lon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
//TODO find how to implement a functional interface in kotlin + use it here & on AttachmentUploadJob (see TODO in DatabaseAttachmentProvider.kt on app side)
|
FileServerAPI.shared.downloadFile(tempFile, attachmentStream.url, MAX_ATTACHMENT_SIZE, attachmentStream.listener)
|
||||||
val listener = SessionServiceAttachment.ProgressListener { override fun onAttachmentProgress(total: Long, progress: Long) { EventBus.getDefault().postSticky(AttachmentProgressEvent(attachmentPointer, total, progress)) } }
|
|
||||||
FileServerAPI.shared.downloadFile(tempFile, attachmentPointer.url, MAX_ATTACHMENT_SIZE, listener)
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return handleFailure(e)
|
return handleFailure(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DECRYPTION
|
||||||
|
|
||||||
// Assume we're retrieving an attachment for an open group server if the digest is not set
|
// Assume we're retrieving an attachment for an open group server if the digest is not set
|
||||||
var stream = if (!attachmentPointer.digest.isPresent) FileInputStream(tempFile)
|
var stream = if (!attachmentStream.digest.isPresent || attachmentStream.key == null) FileInputStream(tempFile)
|
||||||
else AttachmentCipherInputStream.createForAttachment(tempFile, attachmentPointer.size.or(0).toLong(), attachmentPointer.key?.toByteArray(), attachmentPointer.digest.get())
|
else AttachmentCipherInputStream.createForAttachment(tempFile, attachmentStream.length.or(0).toLong(), attachmentStream.key?.toByteArray(), attachmentStream?.digest.get())
|
||||||
|
|
||||||
messageDataProvider.insertAttachment(tsIncomingMessageID, attachmentID, stream)
|
messageDataProvider.insertAttachment(tsIncomingMessageID, attachmentID, stream)
|
||||||
|
|
||||||
|
tempFile.delete()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSuccess() {
|
private fun handleSuccess() {
|
||||||
|
@ -92,40 +92,12 @@ abstract class SessionServiceAttachment protected constructor(val contentType: S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface to receive progress information on upload/download of
|
|
||||||
* an attachment.
|
|
||||||
*/
|
|
||||||
/*interface ProgressListener {
|
|
||||||
/**
|
|
||||||
* Called on a progress change event.
|
|
||||||
*
|
|
||||||
* @param total The total amount to transmit/receive in bytes.
|
|
||||||
* @param progress The amount that has been transmitted/received in bytes thus far
|
|
||||||
*/
|
|
||||||
fun onAttachmentProgress(total: Long, progress: Long)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun newStreamBuilder(): Builder {
|
fun newStreamBuilder(): Builder {
|
||||||
return Builder()
|
return Builder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface to receive progress information on upload/download of
|
|
||||||
* an attachment.
|
|
||||||
*/
|
|
||||||
interface ProgressListener {
|
|
||||||
/**
|
|
||||||
* Called on a progress change event.
|
|
||||||
*
|
|
||||||
* @param total The total amount to transmit/receive in bytes.
|
|
||||||
* @param progress The amount that has been transmitted/received in bytes thus far
|
|
||||||
*/
|
|
||||||
fun onAttachmentProgress(total: Long, progress: Long)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// matches values in AttachmentDatabase.java
|
// matches values in AttachmentDatabase.java
|
||||||
|
@ -22,7 +22,7 @@ class SessionServiceAttachmentStream(val inputStream: InputStream?, contentType:
|
|||||||
|
|
||||||
// Though now required, `digest` may be null for pre-existing records or from
|
// Though now required, `digest` may be null for pre-existing records or from
|
||||||
// messages received from other clients
|
// messages received from other clients
|
||||||
var digest: ByteArray? = null
|
var digest: Optional<ByteArray> = Optional.absent()
|
||||||
|
|
||||||
// This only applies for attachments being uploaded.
|
// This only applies for attachments being uploaded.
|
||||||
var isUploaded: Boolean = false
|
var isUploaded: Boolean = false
|
||||||
@ -48,7 +48,7 @@ class SessionServiceAttachmentStream(val inputStream: InputStream?, contentType:
|
|||||||
|
|
||||||
builder.size = this.length.toInt()
|
builder.size = this.length.toInt()
|
||||||
builder.key = this.key
|
builder.key = this.key
|
||||||
builder.digest = ByteString.copyFrom(this.digest)
|
builder.digest = ByteString.copyFrom(this.digest.get())
|
||||||
builder.flags = if (this.voiceNote) SignalServiceProtos.AttachmentPointer.Flags.VOICE_MESSAGE.number else 0
|
builder.flags = if (this.voiceNote) SignalServiceProtos.AttachmentPointer.Flags.VOICE_MESSAGE.number else 0
|
||||||
|
|
||||||
//TODO I did copy the behavior of iOS below, not sure if that's relevant here...
|
//TODO I did copy the behavior of iOS below, not sure if that's relevant here...
|
||||||
|
@ -185,7 +185,7 @@ open class DotNetAPI {
|
|||||||
/**
|
/**
|
||||||
* Blocks the calling thread.
|
* Blocks the calling thread.
|
||||||
*/
|
*/
|
||||||
fun downloadFile(destination: File, url: String, maxSize: Int, listener: SessionServiceAttachment.ProgressListener?) {
|
fun downloadFile(destination: File, url: String, maxSize: Int, listener: SignalServiceAttachment.ProgressListener?) {
|
||||||
val outputStream = FileOutputStream(destination) // Throws
|
val outputStream = FileOutputStream(destination) // Throws
|
||||||
var remainingAttempts = 4
|
var remainingAttempts = 4
|
||||||
var exception: Exception? = null
|
var exception: Exception? = null
|
||||||
@ -205,7 +205,7 @@ open class DotNetAPI {
|
|||||||
/**
|
/**
|
||||||
* Blocks the calling thread.
|
* Blocks the calling thread.
|
||||||
*/
|
*/
|
||||||
fun downloadFile(outputStream: OutputStream, url: String, maxSize: Int, listener: SessionServiceAttachment.ProgressListener?) {
|
fun downloadFile(outputStream: OutputStream, url: String, maxSize: Int, listener: SignalServiceAttachment.ProgressListener?) {
|
||||||
// We need to throw a PushNetworkException or NonSuccessfulResponseCodeException
|
// We need to throw a PushNetworkException or NonSuccessfulResponseCodeException
|
||||||
// because the underlying Signal logic requires these to work correctly
|
// because the underlying Signal logic requires these to work correctly
|
||||||
val oldPrefixedHost = "https://" + HttpUrl.get(url).host()
|
val oldPrefixedHost = "https://" + HttpUrl.get(url).host()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user