android-smsmms
android-smsmms copied to clipboard
Mms Send Stuck on "Sending"
I have noticed this problem on the following devices: realme 9i android 13 network - vi samesung m53 android 13 network - jio redmi note10s android 13 network - jio
Some of those devices give "error code: 5" and some devices is just stuck on "Sending" without sending anything https://drive.google.com/file/d/1sSI_niLAFBP4gWOlsVRzM1MSjxOYZiJK/view?usp=sharing https://drive.google.com/file/d/1A2tZZ1Zz07bERa1WiBBMpHfYsClKL53f/view?usp=sharing https://drive.google.com/file/d/12rEq8JP0L5mKnP0nxwxjSkVqiNKa5Qh-/view?usp=sharing
Here's my code
fun Context.getSendMessageSettings(): Settings {
val settings = Settings()
settings.useSystemSending = true
settings.deliveryReports = config.enableDeliveryReports
settings.sendLongAsMms = config.sendLongMessageMMS
settings.sendLongAsMmsAfter = 1
settings.group = config.sendGroupMessageMMS
return settings
}
/** Sends the message using the in-app SmsManager API wrappers if it's an SMS or using android-smsmms for MMS. */
fun Context.sendMessageCompat(text: String, addresses: List<String>, subId: Int?, attachments: List<Attachment>, messageId: Long? = null) {
val settings = getSendMessageSettings()
if (subId != null) {
settings.subscriptionId = subId
}
Log.i("subId", subId.toString())
val messagingUtils = messagingUtils
val isMms = attachments.isNotEmpty() || isLongMmsMessage(text, settings) || addresses.size > 1 && settings.group
if (isMms) {
// we send all MMS attachments separately to reduces the chances of hitting provider MMS limit.
if (attachments.isNotEmpty()) {
val lastIndex = attachments.lastIndex
if (attachments.size > 1) {
for (i in 0 until lastIndex) {
val attachment = attachments[i]
messagingUtils.sendMmsMessage("", addresses, attachment, settings, messageId)
}
}
val lastAttachment = attachments[lastIndex]
messagingUtils.sendMmsMessage(text, addresses, lastAttachment, settings, messageId)
} else {
messagingUtils.sendMmsMessage(text, addresses, null, settings, messageId)
}
} else {
try {
messagingUtils.sendSmsMessage(text, addresses.toSet(), settings.subscriptionId, settings.deliveryReports, messageId)
} catch (e: SmsException) {
when (e.errorCode) {
EMPTY_DESTINATION_ADDRESS -> toast(id = R.string.empty_destination_address, length = LENGTH_LONG)
ERROR_PERSISTING_MESSAGE -> toast(id = R.string.unable_to_save_message, length = LENGTH_LONG)
ERROR_SENDING_MESSAGE -> toast(
msg = getString(R.string.unknown_error_occurred_sending_message, e.errorCode),
length = LENGTH_LONG
)
}
} catch (e: Exception) {
showErrorToast(e)
}
}
}
fun sendMmsMessage(text: String, addresses: List<String>, attachment: Attachment?, settings: Settings, messageId: Long? = null) {
val transaction = Transaction(context, settings)
val message = Message(text, addresses.toTypedArray())
if (attachment != null) {
try {
val uri = attachment.getUri()
context.contentResolver.openInputStream(uri)?.use {
val bytes = it.readBytes()
val mimeType = if (attachment.mimetype.isPlainTextMimeType()) {
"application/txt"
} else {
attachment.mimetype
}
val name = attachment.filename
message.addMedia(bytes, mimeType, name)
}
} catch (e: Exception) {
context.showErrorToast(e)
} catch (e: Error) {
context.showErrorToast(e.localizedMessage ?: context.getString(com.simplemobiletools.commons.R.string.unknown_error_occurred))
}
}
val mmsSentIntent = Intent(context, MmsSentReceiver::class.java)
mmsSentIntent.putExtra(MmsSentReceiver.EXTRA_ORIGINAL_RESENT_MESSAGE_ID, messageId)
transaction.setExplicitBroadcastForSentMms(mmsSentIntent)
try {
transaction.sendNewMessage(message)
} catch (e: Exception) {
context.showErrorToast(e)
}
}
@AndroidEntryPoint
class MmsSentReceiver : SendStatusReceiver() {
@Inject
lateinit var cache: Cache
private val myCoroutineScope = CoroutineScope(Dispatchers.IO)
override fun updateAndroidDatabase(context: Context, intent: Intent, receiverResultCode: Int) {
val uri = Uri.parse(intent.getStringExtra(EXTRA_CONTENT_URI))
val originalResentMessageId = intent.getLongExtra(EXTRA_ORIGINAL_RESENT_MESSAGE_ID, -1L)
val messageBox = if (receiverResultCode == Activity.RESULT_OK) {
Telephony.Mms.MESSAGE_BOX_SENT
} else {
val msg = context.getString(R.string.unknown_error_occurred_sending_message, receiverResultCode)
context.toast(msg = msg, length = Toast.LENGTH_LONG)
Telephony.Mms.MESSAGE_BOX_FAILED
}
val values = ContentValues(1).apply {
put(Telephony.Mms.MESSAGE_BOX, messageBox)
}
try {
context.contentResolver.update(uri, values, null, null)
} catch (e: SQLiteException) {
context.showErrorToast(e)
}
// In case of resent message, delete original to prevent duplication
if (originalResentMessageId != -1L) {
myCoroutineScope.launch {
context.deleteMessage(originalResentMessageId, true)
cache.deleteMessage(originalResentMessageId)
}
}
val filePath = intent.getStringExtra(EXTRA_FILE_PATH)
if (filePath != null) {
File(filePath).delete()
}
}
override fun updateAppDatabase(context: Context, intent: Intent, receiverResultCode: Int) {
val messageUri: Uri? = intent.data
if (messageUri != null) {
val messageId = messageUri.lastPathSegment?.toLong() ?: 0L
myCoroutineScope.launch {
if (resultCode != Telephony.Sms.Sent.STATUS_NONE) {
cache.updateMessageStatus(messageId, receiverResultCode)
}
}
}
}
companion object {
private const val EXTRA_CONTENT_URI = "content_uri"
private const val EXTRA_FILE_PATH = "file_path"
const val EXTRA_ORIGINAL_RESENT_MESSAGE_ID = "original_message_id"
}
}