Skip to content

Commit

Permalink
Retry sending failed MMS
Browse files Browse the repository at this point in the history
  • Loading branch information
moezbhatti committed Nov 13, 2019
1 parent d1baad6 commit b8836af
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ class Transaction @JvmOverloads constructor(private val context: Context, settin
*
* @param threadId is the thread id of who to send the message to (can also be set to Transaction.NO_THREAD_ID)
*/
fun sendNewMessage(subId: Int, threadId: Long, addresses: List<String>, parts: List<MMSPart>, subject: String?) {

fun sendNewMessage(subId: Int, threadId: Long, addresses: List<String>, parts: List<MMSPart>, subject: String?, existingUri: Uri?) {
RateController.init(context)
DownloadManager.init(context)

Expand All @@ -95,7 +94,7 @@ class Transaction @JvmOverloads constructor(private val context: Context, settin

val sendReq = buildPdu(context, addresses, subject, parts)
val persister = PduPersister.getPduPersister(context)
val messageUri = persister.persist(sendReq, Uri.parse("content://mms/outbox"), true, true, null)
val messageUri = existingUri ?: persister.persist(sendReq, Uri.parse("content://mms/outbox"), true, true, null)

val sentIntent = Intent(MMS_SENT)
BroadcastUtils.addClassName(context, sentIntent, MMS_SENT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class SendSmsReceiver : BroadcastReceiver() {
?.let(messageRepo::getMessage)
?.let { message ->
val result = goAsync()
retrySending.execute(message) { result.finish() }
retrySending.execute(message.id) { result.finish() }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import android.webkit.MimeTypeMap
import androidx.core.content.contentValuesOf
import com.google.android.mms.ContentType
import com.google.android.mms.MMSPart
import com.google.android.mms.pdu_alt.MultimediaMessagePdu
import com.google.android.mms.pdu_alt.PduPersister
import com.klinker.android.send_message.SmsManagerFactory
import com.klinker.android.send_message.StripAccents
import com.klinker.android.send_message.Transaction
Expand Down Expand Up @@ -330,8 +332,7 @@ class MessageRepositoryImpl @Inject constructor(
.map { attachment -> attachment.vCard.toByteArray() }
.map { vCard -> MMSPart("contact", ContentType.TEXT_VCARD, vCard) }

val transaction = Transaction(context)
transaction.sendNewMessage(subId, threadId, addresses.map(phoneNumberUtils::normalizeNumber), parts, null)
Transaction(context).sendNewMessage(subId, threadId, addresses, parts, null, null)
}
}

Expand Down Expand Up @@ -370,6 +371,25 @@ class MessageRepositoryImpl @Inject constructor(
}
}

override fun resendMms(message: Message) {
val subId = message.subId
val threadId = message.threadId
val pdu = tryOrNull {
PduPersister.getPduPersister(context).load(message.getUri()) as MultimediaMessagePdu
} ?: return

val addresses = pdu.to.map { it.string }.filter { it.isNotBlank() }
val parts = message.parts.mapNotNull { part ->
val bytes = tryOrNull {
context.contentResolver.openInputStream(part.getUri())?.use { inputStream -> inputStream.readBytes() }
} ?: return@mapNotNull null

MMSPart(part.name.orEmpty(), part.type, bytes)
}

Transaction(context).sendNewMessage(subId, threadId, addresses, parts, message.subject, message.getUri())
}

override fun cancelDelayedSms(id: Long) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(getIntentForDelayedSms(id))
Expand Down Expand Up @@ -489,12 +509,17 @@ class MessageRepositoryImpl @Inject constructor(
message?.let {
// Update the message in realm
realm.executeTransaction {
message.boxId = Telephony.Sms.MESSAGE_TYPE_OUTBOX
message.boxId = when (message.isSms()) {
true -> Telephony.Sms.MESSAGE_TYPE_OUTBOX
false -> Telephony.Mms.MESSAGE_BOX_OUTBOX
}
}

// Update the message in the native ContentProvider
val values = ContentValues()
values.put(Telephony.Sms.TYPE, Telephony.Sms.MESSAGE_TYPE_OUTBOX)
val values = when (message.isSms()) {
true -> contentValuesOf(Telephony.Sms.TYPE to Telephony.Sms.MESSAGE_TYPE_OUTBOX)
false -> contentValuesOf(Telephony.Mms.MESSAGE_BOX to Telephony.Mms.MESSAGE_BOX_OUTBOX)
}
context.contentResolver.update(message.getUri(), values, null, null)
}
}
Expand Down
28 changes: 12 additions & 16 deletions domain/src/main/java/com/moez/QKSMS/interactor/RetrySending.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,25 @@
*/
package com.moez.QKSMS.interactor

import com.moez.QKSMS.extensions.mapNotNull
import com.moez.QKSMS.model.Message
import com.moez.QKSMS.repository.MessageRepository
import io.reactivex.Flowable
import javax.inject.Inject

class RetrySending @Inject constructor(private val messageRepo: MessageRepository) : Interactor<Message>() {
class RetrySending @Inject constructor(private val messageRepo: MessageRepository) : Interactor<Long>() {

override fun buildObservable(params: Message): Flowable<Message> {
override fun buildObservable(params: Long): Flowable<Message> {

// We don't want to touch the supplied message on another thread in case it's a live realm
// object, so copy the required fields into a new object that is safe to pass around threads
val message = Message().apply {
id = params.id
type = params.type
address = params.address
body = params.body
subId = params.subId
}

return Flowable.just(message)
.filter { message.isSms() } // TODO support resending failed MMS
.doOnNext { messageRepo.markSending(message.id) }
.doOnNext { messageRepo.sendSms(message) }
return Flowable.just(params)
.mapNotNull(messageRepo::getMessage)
.doOnNext { message -> messageRepo.markSending(message.id) }
.doOnNext { message ->
when (message.isSms()) {
true -> messageRepo.sendSms(message)
false -> messageRepo.resendMms(message)
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ interface MessageRepository {
*/
fun sendSms(message: Message)

fun resendMms(message: Message)

/**
* Attempts to cancel sending the message with the given id
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ class ComposeViewModel @Inject constructor(
view.messageClickIntent
.mapNotNull(messageRepo::getMessage)
.filter { message -> message.isFailedMessage() }
.doOnNext { message -> retrySending.execute(message) }
.doOnNext { message -> retrySending.execute(message.id) }
.autoDisposable(view.scope())
.subscribe()

Expand Down

0 comments on commit b8836af

Please sign in to comment.