mirror of
https://github.com/SimpleMobileTools/Simple-SMS-Messenger.git
synced 2025-06-05 21:49:22 +02:00
Rewrite, move SMS related code into the app
This commit is contained in:
@ -55,6 +55,10 @@ import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog
|
||||
import com.simplemobiletools.smsmessenger.dialogs.ScheduleMessageDialog
|
||||
import com.simplemobiletools.smsmessenger.extensions.*
|
||||
import com.simplemobiletools.smsmessenger.helpers.*
|
||||
import com.simplemobiletools.smsmessenger.messaging.cancelScheduleSendPendingIntent
|
||||
import com.simplemobiletools.smsmessenger.messaging.isLongMmsMessage
|
||||
import com.simplemobiletools.smsmessenger.messaging.scheduleMessage
|
||||
import com.simplemobiletools.smsmessenger.messaging.sendMessageCompat
|
||||
import com.simplemobiletools.smsmessenger.models.*
|
||||
import com.simplemobiletools.smsmessenger.models.ThreadItem.*
|
||||
import kotlinx.android.synthetic.main.activity_thread.*
|
||||
@ -1167,7 +1171,7 @@ class ThreadActivity : SimpleActivity() {
|
||||
|
||||
try {
|
||||
refreshedSinceSent = false
|
||||
sendMessage(text, addresses, subscriptionId, attachments)
|
||||
sendMessageCompat(text, addresses, subscriptionId, attachments)
|
||||
ensureBackgroundThread {
|
||||
val messageIds = messages.map { it.id }
|
||||
val message = getMessages(threadId, getImageResolutions = true, limit = 1).firstOrNull { it.id !in messageIds }
|
||||
@ -1347,7 +1351,7 @@ class ThreadActivity : SimpleActivity() {
|
||||
|
||||
private fun isMmsMessage(text: String): Boolean {
|
||||
val isGroupMms = participants.size > 1 && config.sendGroupMessageMMS
|
||||
val isLongMmsMessage = isLongMmsMessage(text) && config.sendLongMessageMMS
|
||||
val isLongMmsMessage = isLongMmsMessage(text)
|
||||
return getAttachmentSelections().isNotEmpty() || isGroupMms || isLongMmsMessage
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.simplemobiletools.smsmessenger.extensions
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.content.ContentResolver
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
@ -18,7 +19,6 @@ import android.text.TextUtils
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.klinker.android.send_message.Transaction.getAddressSeparator
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
import com.simplemobiletools.commons.models.PhoneNumber
|
||||
@ -31,6 +31,9 @@ import com.simplemobiletools.smsmessenger.interfaces.AttachmentsDao
|
||||
import com.simplemobiletools.smsmessenger.interfaces.ConversationsDao
|
||||
import com.simplemobiletools.smsmessenger.interfaces.MessageAttachmentsDao
|
||||
import com.simplemobiletools.smsmessenger.interfaces.MessagesDao
|
||||
import com.simplemobiletools.smsmessenger.messaging.MessagingUtils
|
||||
import com.simplemobiletools.smsmessenger.messaging.MessagingUtils.Companion.ADDRESS_SEPARATOR
|
||||
import com.simplemobiletools.smsmessenger.messaging.SmsSender
|
||||
import com.simplemobiletools.smsmessenger.models.*
|
||||
import me.leolin.shortcutbadger.ShortcutBadger
|
||||
import java.io.FileNotFoundException
|
||||
@ -49,6 +52,10 @@ val Context.messagesDB: MessagesDao get() = getMessagesDB().MessagesDao()
|
||||
|
||||
val Context.notificationHelper get() = NotificationHelper(this)
|
||||
|
||||
val Context.messagingUtils get() = MessagingUtils(this)
|
||||
|
||||
val Context.smsSender get() = SmsSender.getInstance(applicationContext as Application)
|
||||
|
||||
fun Context.getMessages(
|
||||
threadId: Long,
|
||||
getImageResolutions: Boolean,
|
||||
@ -103,7 +110,7 @@ fun Context.getMessages(
|
||||
val thread = cursor.getLongValue(Sms.THREAD_ID)
|
||||
val subscriptionId = cursor.getIntValue(Sms.SUBSCRIPTION_ID)
|
||||
val status = cursor.getIntValue(Sms.STATUS)
|
||||
val participants = senderNumber.split(getAddressSeparator()).map { number ->
|
||||
val participants = senderNumber.split(ADDRESS_SEPARATOR).map { number ->
|
||||
val phoneNumber = PhoneNumber(number, 0, "", number)
|
||||
val participantPhoto = getNameAndPhotoFromPhoneNumber(number)
|
||||
SimpleContact(0, 0, participantPhoto.name, photoUri, arrayListOf(phoneNumber), ArrayList(), ArrayList())
|
||||
@ -648,26 +655,6 @@ fun Context.markThreadMessagesUnread(threadId: Long) {
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.updateMessageType(id: Long, type: Int) {
|
||||
val uri = Sms.CONTENT_URI
|
||||
val contentValues = ContentValues().apply {
|
||||
put(Sms.TYPE, type)
|
||||
}
|
||||
val selection = "${Sms._ID} = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
contentResolver.update(uri, contentValues, selection, selectionArgs)
|
||||
}
|
||||
|
||||
fun Context.updateMessageStatus(id: Long, status: Int) {
|
||||
val uri = Sms.CONTENT_URI
|
||||
val contentValues = ContentValues().apply {
|
||||
put(Sms.STATUS, status)
|
||||
}
|
||||
val selection = "${Sms._ID} = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
contentResolver.update(uri, contentValues, selection, selectionArgs)
|
||||
}
|
||||
|
||||
fun Context.updateUnreadCountBadge(conversations: List<Conversation>) {
|
||||
val unreadCount = conversations.count { !it.read }
|
||||
if (unreadCount == 0) {
|
||||
|
@ -2,6 +2,10 @@ package com.simplemobiletools.smsmessenger.helpers
|
||||
|
||||
import com.simplemobiletools.smsmessenger.models.Events
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.DateTimeZone
|
||||
import kotlin.math.abs
|
||||
import kotlin.random.Random
|
||||
|
||||
const val THREAD_ID = "thread_id"
|
||||
const val THREAD_TITLE = "thread_title"
|
||||
@ -81,3 +85,10 @@ const val PICK_CONTACT_INTENT = 48
|
||||
fun refreshMessages() {
|
||||
EventBus.getDefault().post(Events.RefreshMessages())
|
||||
}
|
||||
|
||||
/** Not to be used with real messages persisted in the telephony db. This is for internal use only (e.g. scheduled messages, notification ids etc). */
|
||||
fun generateRandomId(length: Int = 9): Long {
|
||||
val millis = DateTime.now(DateTimeZone.UTC).millis
|
||||
val random = abs(Random(millis).nextLong())
|
||||
return random.toString().takeLast(length).toLong()
|
||||
}
|
||||
|
@ -1,111 +0,0 @@
|
||||
package com.simplemobiletools.smsmessenger.helpers
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.app.AlarmManagerCompat
|
||||
import com.klinker.android.send_message.Settings
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import com.klinker.android.send_message.Utils
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
import com.simplemobiletools.smsmessenger.extensions.isPlainTextMimeType
|
||||
import com.simplemobiletools.smsmessenger.models.Attachment
|
||||
import com.simplemobiletools.smsmessenger.models.Message
|
||||
import com.simplemobiletools.smsmessenger.receivers.ScheduledMessageReceiver
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusDeliveredReceiver
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusSentReceiver
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.DateTimeZone
|
||||
import kotlin.math.abs
|
||||
import kotlin.random.Random
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
fun Context.sendMessage(text: String, addresses: List<String>, subscriptionId: Int?, attachments: List<Attachment>) {
|
||||
val settings = getSendMessageSettings()
|
||||
if (subscriptionId != null) {
|
||||
settings.subscriptionId = subscriptionId
|
||||
}
|
||||
|
||||
val transaction = Transaction(this, settings)
|
||||
val message = com.klinker.android.send_message.Message(text, addresses.toTypedArray())
|
||||
|
||||
if (attachments.isNotEmpty()) {
|
||||
for (attachment in attachments) {
|
||||
try {
|
||||
val uri = attachment.getUri()
|
||||
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, name)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
} catch (e: Error) {
|
||||
showErrorToast(e.localizedMessage ?: getString(R.string.unknown_error_occurred))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val smsSentIntent = Intent(this, SmsStatusSentReceiver::class.java)
|
||||
val deliveredIntent = Intent(this, SmsStatusDeliveredReceiver::class.java)
|
||||
|
||||
transaction.setExplicitBroadcastForSentSms(smsSentIntent)
|
||||
transaction.setExplicitBroadcastForDeliveredSms(deliveredIntent)
|
||||
try {
|
||||
transaction.sendNewMessage(message)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.getScheduleSendPendingIntent(message: Message): PendingIntent {
|
||||
val intent = Intent(this, ScheduledMessageReceiver::class.java)
|
||||
intent.putExtra(THREAD_ID, message.threadId)
|
||||
intent.putExtra(SCHEDULED_MESSAGE_ID, message.id)
|
||||
|
||||
val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
return PendingIntent.getBroadcast(this, message.id.toInt(), intent, flags)
|
||||
}
|
||||
|
||||
fun Context.scheduleMessage(message: Message) {
|
||||
val pendingIntent = getScheduleSendPendingIntent(message)
|
||||
val triggerAtMillis = message.millis()
|
||||
|
||||
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent)
|
||||
}
|
||||
|
||||
fun Context.cancelScheduleSendPendingIntent(messageId: Long) {
|
||||
val intent = Intent(this, ScheduledMessageReceiver::class.java)
|
||||
val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
PendingIntent.getBroadcast(this, messageId.toInt(), intent, flags).cancel()
|
||||
}
|
||||
|
||||
fun Context.isLongMmsMessage(text: String): Boolean {
|
||||
val settings = getSendMessageSettings()
|
||||
return Utils.getNumPages(settings, text) > settings.sendLongAsMmsAfter
|
||||
}
|
||||
|
||||
/** Not to be used with real messages persisted in the telephony db. This is for internal use only (e.g. scheduled messages). */
|
||||
fun generateRandomId(length: Int = 9): Long {
|
||||
val millis = DateTime.now(DateTimeZone.UTC).millis
|
||||
val random = abs(Random(millis).nextLong())
|
||||
return random.toString().takeLast(length).toLong()
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.simplemobiletools.smsmessenger.messaging
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.SmsMessage
|
||||
import android.widget.Toast.LENGTH_LONG
|
||||
import com.klinker.android.send_message.Settings
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
import com.simplemobiletools.smsmessenger.extensions.messagingUtils
|
||||
import com.simplemobiletools.smsmessenger.messaging.SmsException.Companion.EMPTY_DESTINATION_ADDRESS
|
||||
import com.simplemobiletools.smsmessenger.messaging.SmsException.Companion.ERROR_PERSISTING_MESSAGE
|
||||
import com.simplemobiletools.smsmessenger.messaging.SmsException.Companion.ERROR_SENDING_MESSAGE
|
||||
import com.simplemobiletools.smsmessenger.models.Attachment
|
||||
|
||||
@Deprecated("TODO: Move/rewrite messaging config code into the app.")
|
||||
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
|
||||
}
|
||||
|
||||
fun Context.isLongMmsMessage(text: String, settings: Settings = getSendMessageSettings()): Boolean {
|
||||
val data = SmsMessage.calculateLength(text, false)
|
||||
val numPages = data.first()
|
||||
return numPages > settings.sendLongAsMmsAfter && settings.sendLongAsMms
|
||||
}
|
||||
|
||||
/** 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>) {
|
||||
val settings = getSendMessageSettings()
|
||||
if (subId != null) {
|
||||
settings.subscriptionId = subId
|
||||
}
|
||||
|
||||
val isMms = attachments.isNotEmpty() || isLongMmsMessage(text, settings) || addresses.size > 1 && settings.group
|
||||
if (isMms) {
|
||||
messagingUtils.sendMmsMessage(text, addresses, attachments, settings)
|
||||
} else {
|
||||
try {
|
||||
messagingUtils.sendSmsMessage(text, addresses.toSet(), settings.subscriptionId, settings.deliveryReports)
|
||||
} 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(id = R.string.unknown_error_occurred, length = LENGTH_LONG)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,147 @@
|
||||
package com.simplemobiletools.smsmessenger.messaging
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.provider.Telephony.Sms
|
||||
import android.telephony.SmsManager
|
||||
import android.widget.Toast
|
||||
import com.klinker.android.send_message.Message
|
||||
import com.klinker.android.send_message.Settings
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.commons.extensions.toast
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.getThreadId
|
||||
import com.simplemobiletools.smsmessenger.extensions.isPlainTextMimeType
|
||||
import com.simplemobiletools.smsmessenger.extensions.smsSender
|
||||
import com.simplemobiletools.smsmessenger.messaging.SmsException.Companion.ERROR_PERSISTING_MESSAGE
|
||||
import com.simplemobiletools.smsmessenger.models.Attachment
|
||||
|
||||
class MessagingUtils(val context: Context) {
|
||||
|
||||
/**
|
||||
* Insert an SMS to the given URI with thread_id specified.
|
||||
*/
|
||||
private fun insertSmsMessage(
|
||||
subId: Int, dest: String, text: String, timestamp: Long, threadId: Long,
|
||||
status: Int = Sms.STATUS_NONE, type: Int = Sms.MESSAGE_TYPE_OUTBOX
|
||||
): Uri {
|
||||
val response: Uri?
|
||||
val values = ContentValues().apply {
|
||||
put(Sms.ADDRESS, dest)
|
||||
put(Sms.DATE, timestamp)
|
||||
put(Sms.READ, 1)
|
||||
put(Sms.SEEN, 1)
|
||||
put(Sms.BODY, text)
|
||||
|
||||
// insert subscription id only if it is a valid one.
|
||||
if (subId != Settings.DEFAULT_SUBSCRIPTION_ID) {
|
||||
put(Sms.SUBSCRIPTION_ID, subId)
|
||||
}
|
||||
|
||||
if (status != Sms.STATUS_NONE) {
|
||||
put(Sms.STATUS, status)
|
||||
}
|
||||
if (type != Sms.MESSAGE_TYPE_ALL) {
|
||||
put(Sms.TYPE, type)
|
||||
}
|
||||
if (threadId != -1L) {
|
||||
put(Sms.THREAD_ID, threadId)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
response = context.contentResolver.insert(Sms.CONTENT_URI, values)
|
||||
} catch (e: Exception) {
|
||||
throw SmsException(ERROR_PERSISTING_MESSAGE, e)
|
||||
}
|
||||
return response ?: throw SmsException(ERROR_PERSISTING_MESSAGE)
|
||||
}
|
||||
|
||||
/** Send an SMS message given [text] and [addresses]. A [SmsException] is thrown in case any errors occur. */
|
||||
fun sendSmsMessage(
|
||||
text: String, addresses: Set<String>, subId: Int, requireDeliveryReport: Boolean
|
||||
) {
|
||||
if (addresses.size > 1) {
|
||||
// insert a dummy message for this thread if it is a group message
|
||||
val broadCastThreadId = context.getThreadId(addresses.toSet())
|
||||
val mergedAddresses = addresses.joinToString(ADDRESS_SEPARATOR)
|
||||
insertSmsMessage(
|
||||
subId = subId, dest = mergedAddresses, text = text,
|
||||
timestamp = System.currentTimeMillis(), threadId = broadCastThreadId,
|
||||
status = Sms.Sent.STATUS_COMPLETE, type = Sms.Sent.MESSAGE_TYPE_SENT
|
||||
)
|
||||
}
|
||||
|
||||
for (address in addresses) {
|
||||
val threadId = context.getThreadId(address)
|
||||
val messageUri = insertSmsMessage(
|
||||
subId = subId, dest = address, text = text,
|
||||
timestamp = System.currentTimeMillis(), threadId = threadId
|
||||
)
|
||||
context.smsSender.sendMessage(
|
||||
subId = subId, destination = address, body = text, serviceCenter = null,
|
||||
requireDeliveryReport = requireDeliveryReport, messageUri = messageUri
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("TODO: Move/rewrite MMS code into the app.")
|
||||
fun sendMmsMessage(text: String, addresses: List<String>, attachments: List<Attachment>, settings: Settings) {
|
||||
val transaction = Transaction(context, settings)
|
||||
val message = Message(text, addresses.toTypedArray())
|
||||
|
||||
if (attachments.isNotEmpty()) {
|
||||
for (attachment in attachments) {
|
||||
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, name)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context.showErrorToast(e)
|
||||
} catch (e: Error) {
|
||||
context.showErrorToast(e.localizedMessage ?: context.getString(R.string.unknown_error_occurred))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
transaction.sendNewMessage(message)
|
||||
} catch (e: Exception) {
|
||||
context.showErrorToast(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun maybeShowErrorToast(resultCode: Int, errorCode: Int) {
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
val msgId = if (errorCode != SendStatusReceiver.NO_ERROR_CODE) {
|
||||
context.getString(R.string.carrier_send_error)
|
||||
} else {
|
||||
when (resultCode) {
|
||||
SmsManager.RESULT_ERROR_NO_SERVICE -> context.getString(R.string.error_service_is_unavailable)
|
||||
SmsManager.RESULT_ERROR_RADIO_OFF -> context.getString(R.string.error_radio_turned_off)
|
||||
else -> {
|
||||
context.getString(R.string.unknown_error_occurred_sending_message, resultCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
context.toast(msg = msgId, length = Toast.LENGTH_LONG)
|
||||
} else {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ADDRESS_SEPARATOR = "|"
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.simplemobiletools.smsmessenger.messaging
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.app.AlarmManagerCompat
|
||||
import com.simplemobiletools.smsmessenger.helpers.SCHEDULED_MESSAGE_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||
import com.simplemobiletools.smsmessenger.models.Message
|
||||
import com.simplemobiletools.smsmessenger.receivers.ScheduledMessageReceiver
|
||||
|
||||
/**
|
||||
* All things related to scheduled messages are here.
|
||||
*/
|
||||
|
||||
fun Context.getScheduleSendPendingIntent(message: Message): PendingIntent {
|
||||
val intent = Intent(this, ScheduledMessageReceiver::class.java)
|
||||
intent.putExtra(THREAD_ID, message.threadId)
|
||||
intent.putExtra(SCHEDULED_MESSAGE_ID, message.id)
|
||||
|
||||
val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
return PendingIntent.getBroadcast(this, message.id.toInt(), intent, flags)
|
||||
}
|
||||
|
||||
fun Context.scheduleMessage(message: Message) {
|
||||
val pendingIntent = getScheduleSendPendingIntent(message)
|
||||
val triggerAtMillis = message.millis()
|
||||
|
||||
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, triggerAtMillis, pendingIntent)
|
||||
}
|
||||
|
||||
fun Context.cancelScheduleSendPendingIntent(messageId: Long) {
|
||||
val intent = Intent(this, ScheduledMessageReceiver::class.java)
|
||||
val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
PendingIntent.getBroadcast(this, messageId.toInt(), intent, flags).cancel()
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.simplemobiletools.smsmessenger.messaging
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
|
||||
abstract class SendStatusReceiver : BroadcastReceiver() {
|
||||
// Updates the status of the message in the internal database
|
||||
abstract fun updateAndroidDatabase(context: Context, intent: Intent, receiverResultCode: Int)
|
||||
|
||||
// allows the implementer to update the status of the message in their database
|
||||
abstract fun updateAppDatabase(context: Context, intent: Intent, receiverResultCode: Int)
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val resultCode = resultCode
|
||||
ensureBackgroundThread {
|
||||
updateAndroidDatabase(context, intent, resultCode)
|
||||
updateAppDatabase(context, intent, resultCode)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MESSAGE_SENT_ACTION = "com.simplemobiletools.smsmessenger.receiver.SendStatusReceiver.MESSAGE_SENT"
|
||||
const val MESSAGE_DELIVERED_ACTION = "com.simplemobiletools.smsmessenger.receiver.SendStatusReceiver.MESSAGE_DELIVERED"
|
||||
|
||||
// Defined by platform, but no constant provided. See docs for SmsManager.sendTextMessage.
|
||||
const val EXTRA_ERROR_CODE = "errorCode"
|
||||
const val EXTRA_SUB_ID = "subId"
|
||||
|
||||
const val NO_ERROR_CODE = -1
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.simplemobiletools.smsmessenger.messaging
|
||||
|
||||
class SmsException(val errorCode: Int, val exception: Exception? = null) : Exception() {
|
||||
companion object {
|
||||
const val EMPTY_DESTINATION_ADDRESS = 0
|
||||
const val ERROR_PERSISTING_MESSAGE = 1
|
||||
const val ERROR_SENDING_MESSAGE = 2
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.simplemobiletools.smsmessenger.messaging
|
||||
|
||||
import android.telephony.SmsManager
|
||||
import com.klinker.android.send_message.Settings
|
||||
|
||||
private var smsManagerInstance: SmsManager? = null
|
||||
private var associatedSubId: Int = -1
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun getSmsManager(subId: Int): SmsManager {
|
||||
if (smsManagerInstance == null || subId != associatedSubId) {
|
||||
smsManagerInstance = if (subId != Settings.DEFAULT_SUBSCRIPTION_ID) {
|
||||
try {
|
||||
smsManagerInstance = SmsManager.getSmsManagerForSubscriptionId(subId)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
smsManagerInstance ?: SmsManager.getDefault()
|
||||
} else {
|
||||
SmsManager.getDefault()
|
||||
}
|
||||
associatedSubId = subId
|
||||
}
|
||||
return smsManagerInstance!!
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package com.simplemobiletools.smsmessenger.messaging
|
||||
|
||||
import android.app.Application
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import com.simplemobiletools.smsmessenger.messaging.SmsException.Companion.EMPTY_DESTINATION_ADDRESS
|
||||
import com.simplemobiletools.smsmessenger.messaging.SmsException.Companion.ERROR_SENDING_MESSAGE
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusDeliveredReceiver
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusSentReceiver
|
||||
|
||||
/** Class that sends chat message via SMS. */
|
||||
class SmsSender(val app: Application) {
|
||||
|
||||
// not sure what to do about this yet. this is the default as per android-smsmms
|
||||
private val sendMultipartSmsAsSeparateMessages = false
|
||||
|
||||
// This should be called from a RequestWriter queue thread
|
||||
fun sendMessage(
|
||||
subId: Int, destination: String, body: String, serviceCenter: String?,
|
||||
requireDeliveryReport: Boolean, messageUri: Uri
|
||||
) {
|
||||
var dest = destination
|
||||
if (body.isEmpty()) {
|
||||
throw IllegalArgumentException("SmsSender: empty text message")
|
||||
}
|
||||
// remove spaces and dashes from destination number
|
||||
// (e.g. "801 555 1212" -> "8015551212")
|
||||
// (e.g. "+8211-123-4567" -> "+82111234567")
|
||||
dest = PhoneNumberUtils.stripSeparators(dest)
|
||||
|
||||
if (dest.isEmpty()) {
|
||||
throw SmsException(EMPTY_DESTINATION_ADDRESS)
|
||||
}
|
||||
// Divide the input message by SMS length limit
|
||||
val smsManager = getSmsManager(subId)
|
||||
val messages = smsManager.divideMessage(body)
|
||||
if (messages == null || messages.size < 1) {
|
||||
throw SmsException(ERROR_SENDING_MESSAGE)
|
||||
}
|
||||
// Actually send the sms
|
||||
sendInternal(
|
||||
subId, dest, messages, serviceCenter, requireDeliveryReport, messageUri
|
||||
)
|
||||
}
|
||||
|
||||
// Actually sending the message using SmsManager
|
||||
private fun sendInternal(
|
||||
subId: Int, dest: String,
|
||||
messages: ArrayList<String>, serviceCenter: String?,
|
||||
requireDeliveryReport: Boolean, messageUri: Uri
|
||||
) {
|
||||
val smsManager = getSmsManager(subId)
|
||||
val messageCount = messages.size
|
||||
val deliveryIntents = ArrayList<PendingIntent?>(messageCount)
|
||||
val sentIntents = ArrayList<PendingIntent>(messageCount)
|
||||
|
||||
val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
|
||||
for (i in 0 until messageCount) {
|
||||
// Make pending intents different for each message part
|
||||
val partId = if (messageCount <= 1) 0 else i + 1
|
||||
if (requireDeliveryReport && i == messageCount - 1) {
|
||||
deliveryIntents.add(
|
||||
PendingIntent.getBroadcast(
|
||||
app,
|
||||
partId,
|
||||
getDeliveredStatusIntent(messageUri, subId),
|
||||
flags
|
||||
)
|
||||
)
|
||||
} else {
|
||||
deliveryIntents.add(null)
|
||||
}
|
||||
sentIntents.add(
|
||||
PendingIntent.getBroadcast(
|
||||
app,
|
||||
partId,
|
||||
getSendStatusIntent(messageUri, subId),
|
||||
flags
|
||||
)
|
||||
)
|
||||
}
|
||||
try {
|
||||
if (sendMultipartSmsAsSeparateMessages) {
|
||||
// If multipart sms is not supported, send them as separate messages
|
||||
for (i in 0 until messageCount) {
|
||||
smsManager.sendTextMessage(
|
||||
dest,
|
||||
serviceCenter,
|
||||
messages[i],
|
||||
sentIntents[i],
|
||||
deliveryIntents[i]
|
||||
)
|
||||
}
|
||||
} else {
|
||||
smsManager.sendMultipartTextMessage(
|
||||
dest, serviceCenter, messages, sentIntents, deliveryIntents
|
||||
)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
throw SmsException(ERROR_SENDING_MESSAGE, e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSendStatusIntent(requestUri: Uri, subId: Int): Intent {
|
||||
val intent = Intent(SendStatusReceiver.MESSAGE_SENT_ACTION, requestUri, app, SmsStatusSentReceiver::class.java)
|
||||
intent.putExtra(SendStatusReceiver.EXTRA_SUB_ID, subId)
|
||||
return intent
|
||||
}
|
||||
|
||||
private fun getDeliveredStatusIntent(requestUri: Uri, subId: Int): Intent {
|
||||
val intent = Intent(SendStatusReceiver.MESSAGE_DELIVERED_ACTION, requestUri, app, SmsStatusDeliveredReceiver::class.java)
|
||||
intent.putExtra(SendStatusReceiver.EXTRA_SUB_ID, subId)
|
||||
return intent
|
||||
}
|
||||
|
||||
companion object {
|
||||
private var instance: SmsSender? = null
|
||||
fun getInstance(app: Application): SmsSender {
|
||||
if (instance == null) {
|
||||
instance = SmsSender(app)
|
||||
}
|
||||
return instance!!
|
||||
}
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@ import com.simplemobiletools.smsmessenger.extensions.*
|
||||
import com.simplemobiletools.smsmessenger.helpers.REPLY
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_NUMBER
|
||||
import com.simplemobiletools.smsmessenger.helpers.sendMessage
|
||||
import com.simplemobiletools.smsmessenger.messaging.sendMessageCompat
|
||||
|
||||
class DirectReplyReceiver : BroadcastReceiver() {
|
||||
@SuppressLint("MissingPermission")
|
||||
@ -38,7 +38,7 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
||||
|
||||
ensureBackgroundThread {
|
||||
try {
|
||||
context.sendMessage(body, listOf(address), subscriptionId, emptyList())
|
||||
context.sendMessageCompat(body, listOf(address), subscriptionId, emptyList())
|
||||
val message = context.getMessages(threadId, getImageResolutions = false, includeScheduledMessages = false, limit = 1).lastOrNull()
|
||||
if (message != null) {
|
||||
context.messagesDB.insertOrUpdate(message)
|
||||
|
@ -1,15 +1,44 @@
|
||||
package com.simplemobiletools.smsmessenger.receivers
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.sqlite.SQLiteException
|
||||
import android.net.Uri
|
||||
import android.provider.Telephony
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
import com.simplemobiletools.smsmessenger.messaging.SendStatusReceiver
|
||||
import java.io.File
|
||||
|
||||
class MmsSentReceiver : com.klinker.android.send_message.MmsSentReceiver() {
|
||||
override fun onMessageStatusUpdated(context: Context?, intent: Intent?, resultCode: Int) {
|
||||
super.onMessageStatusUpdated(context, intent, resultCode)
|
||||
/** Handles updating databases and states when a MMS message is sent. */
|
||||
class MmsSentReceiver : SendStatusReceiver() {
|
||||
|
||||
override fun updateAndroidDatabase(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
val uri = Uri.parse(intent.getStringExtra(EXTRA_CONTENT_URI))
|
||||
val values = ContentValues(1)
|
||||
values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_SENT)
|
||||
try {
|
||||
context.contentResolver.update(uri, values, null, null)
|
||||
} catch (e: SQLiteException) {
|
||||
context.showErrorToast(e)
|
||||
}
|
||||
|
||||
val filePath = intent.getStringExtra(EXTRA_FILE_PATH)
|
||||
if (filePath != null) {
|
||||
File(filePath).delete()
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateAppDatabase(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
refreshMessages()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val EXTRA_CONTENT_URI = "content_uri"
|
||||
private const val EXTRA_FILE_PATH = "file_path"
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import com.simplemobiletools.smsmessenger.extensions.messagesDB
|
||||
import com.simplemobiletools.smsmessenger.helpers.SCHEDULED_MESSAGE_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
import com.simplemobiletools.smsmessenger.helpers.sendMessage
|
||||
import com.simplemobiletools.smsmessenger.messaging.sendMessageCompat
|
||||
|
||||
class ScheduledMessageReceiver : BroadcastReceiver() {
|
||||
|
||||
@ -46,7 +46,7 @@ class ScheduledMessageReceiver : BroadcastReceiver() {
|
||||
|
||||
try {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
context.sendMessage(message.body, addresses, message.subscriptionId, attachments)
|
||||
context.sendMessageCompat(message.body, addresses, message.subscriptionId, attachments)
|
||||
}
|
||||
|
||||
// delete temporary conversation and message as it's already persisted to the telephony db now
|
||||
|
@ -1,26 +1,90 @@
|
||||
package com.simplemobiletools.smsmessenger.receivers
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Telephony
|
||||
import com.klinker.android.send_message.DeliveredReceiver
|
||||
import android.provider.Telephony.Sms
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.smsmessenger.extensions.messagesDB
|
||||
import com.simplemobiletools.smsmessenger.extensions.updateMessageStatus
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
import com.simplemobiletools.smsmessenger.messaging.SendStatusReceiver
|
||||
|
||||
class SmsStatusDeliveredReceiver : DeliveredReceiver() {
|
||||
/** Handles updating databases and states when a sent SMS message is delivered. */
|
||||
class SmsStatusDeliveredReceiver : SendStatusReceiver() {
|
||||
|
||||
override fun onMessageStatusUpdated(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
if (intent.extras?.containsKey("message_uri") == true) {
|
||||
val uri = Uri.parse(intent.getStringExtra("message_uri"))
|
||||
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
|
||||
override fun updateAndroidDatabase(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
val uri: Uri? = intent.data
|
||||
val resultCode = resultCode
|
||||
|
||||
try {
|
||||
when (resultCode) {
|
||||
Activity.RESULT_OK -> {
|
||||
if (uri != null) {
|
||||
val values = ContentValues().apply {
|
||||
put(Sms.Sent.STATUS, Sms.Sent.STATUS_COMPLETE)
|
||||
put(Sms.Sent.DATE_SENT, System.currentTimeMillis())
|
||||
put(Sms.Sent.READ, true)
|
||||
}
|
||||
context.contentResolver.update(uri, values, null, null)
|
||||
} else {
|
||||
updateLatestSmsStatus(context, status = Sms.Sent.STATUS_COMPLETE, read = true, date = System.currentTimeMillis())
|
||||
}
|
||||
}
|
||||
Activity.RESULT_CANCELED -> {
|
||||
if (uri != null) {
|
||||
val values = ContentValues().apply {
|
||||
put(Sms.Sent.STATUS, Sms.Sent.STATUS_FAILED)
|
||||
put(Sms.Sent.DATE_SENT, System.currentTimeMillis())
|
||||
put(Sms.Sent.READ, true)
|
||||
put(Sms.Sent.ERROR_CODE, resultCode)
|
||||
}
|
||||
context.contentResolver.update(uri, values, null, null)
|
||||
} else {
|
||||
updateLatestSmsStatus(context, status = Sms.Sent.STATUS_FAILED, read = true, errorCode = resultCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("Range")
|
||||
private fun updateLatestSmsStatus(context: Context, status: Int, read: Boolean, date: Long = -1L, errorCode: Int = -1) {
|
||||
val query = context.contentResolver.query(Sms.Sent.CONTENT_URI, null, null, null, "date desc")
|
||||
|
||||
// mark message as delivered in database
|
||||
if (query!!.moveToFirst()) {
|
||||
val id = query.getString(query.getColumnIndex(Sms.Sent._ID))
|
||||
|
||||
val values = ContentValues().apply {
|
||||
put(Sms.Sent.STATUS, status)
|
||||
put(Sms.Sent.READ, read)
|
||||
|
||||
if (date != -1L) {
|
||||
put(Sms.Sent.DATE_SENT, date)
|
||||
}
|
||||
if (errorCode != -1) {
|
||||
put(Sms.Sent.ERROR_CODE, errorCode)
|
||||
}
|
||||
}
|
||||
|
||||
context.contentResolver.update(Sms.Sent.CONTENT_URI, values, "_id=$id", null)
|
||||
}
|
||||
query.close()
|
||||
}
|
||||
|
||||
override fun updateAppDatabase(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
val uri = intent.data
|
||||
if (uri != null) {
|
||||
val messageId = uri.lastPathSegment?.toLong() ?: 0L
|
||||
ensureBackgroundThread {
|
||||
val status = Telephony.Sms.STATUS_COMPLETE
|
||||
context.updateMessageStatus(messageId, status)
|
||||
val status = Sms.Sent.STATUS_COMPLETE
|
||||
val updated = context.messagesDB.updateStatus(messageId, status)
|
||||
if (updated == 0) {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
|
@ -1,35 +1,98 @@
|
||||
package com.simplemobiletools.smsmessenger.receivers
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Telephony
|
||||
import android.provider.Telephony.Sms
|
||||
import android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE
|
||||
import android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE
|
||||
import android.telephony.SmsManager.RESULT_ERROR_NULL_PDU
|
||||
import android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import com.klinker.android.send_message.SentReceiver
|
||||
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.smsmessenger.extensions.*
|
||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
import com.simplemobiletools.smsmessenger.messaging.SendStatusReceiver
|
||||
|
||||
class SmsStatusSentReceiver : SentReceiver() {
|
||||
/** Handles updating databases and states when a SMS message is sent. */
|
||||
@SuppressLint("Range")
|
||||
class SmsStatusSentReceiver : SendStatusReceiver() {
|
||||
|
||||
override fun onMessageStatusUpdated(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
if (intent.extras?.containsKey("message_uri") == true) {
|
||||
val uri = Uri.parse(intent.getStringExtra("message_uri"))
|
||||
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
|
||||
override fun updateAndroidDatabase(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
val messageUri: Uri? = intent.data
|
||||
val resultCode = resultCode
|
||||
|
||||
try {
|
||||
when (resultCode) {
|
||||
Activity.RESULT_OK -> if (messageUri != null) {
|
||||
try {
|
||||
val values = ContentValues()
|
||||
values.put(Sms.Outbox.TYPE, Sms.MESSAGE_TYPE_SENT)
|
||||
values.put(Sms.Outbox.READ, 1)
|
||||
context.contentResolver.update(messageUri, values, null, null)
|
||||
} catch (e: NullPointerException) {
|
||||
updateLatestSms(context = context, type = Sms.MESSAGE_TYPE_SENT, read = 1)
|
||||
}
|
||||
} else {
|
||||
updateLatestSms(context = context, type = Sms.MESSAGE_TYPE_FAILED, read = 1)
|
||||
}
|
||||
RESULT_ERROR_GENERIC_FAILURE, RESULT_ERROR_NO_SERVICE, RESULT_ERROR_NULL_PDU, RESULT_ERROR_RADIO_OFF -> {
|
||||
if (messageUri != null) {
|
||||
val values = ContentValues()
|
||||
values.put(Sms.Outbox.TYPE, Sms.MESSAGE_TYPE_FAILED)
|
||||
values.put(Sms.Outbox.READ, true)
|
||||
values.put(Sms.Outbox.ERROR_CODE, resultCode)
|
||||
context.contentResolver.update(messageUri, values, null, null)
|
||||
} else {
|
||||
updateLatestSms(context = context, type = Sms.MESSAGE_TYPE_FAILED, read = 1, resultCode = resultCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
context.messagingUtils.maybeShowErrorToast(
|
||||
resultCode = resultCode,
|
||||
errorCode = intent.getIntExtra(EXTRA_ERROR_CODE, NO_ERROR_CODE)
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateLatestSms(context: Context, type: Int, read: Int, resultCode: Int = -1) {
|
||||
val query = context.contentResolver.query(Sms.Outbox.CONTENT_URI, null, null, null, null)
|
||||
|
||||
if (query != null && query.moveToFirst()) {
|
||||
val id = query.getString(query.getColumnIndex(Sms.Outbox._ID))
|
||||
val values = ContentValues()
|
||||
values.put(Sms.Outbox.TYPE, type)
|
||||
values.put(Sms.Outbox.READ, read)
|
||||
if (resultCode != -1) {
|
||||
values.put(Sms.Outbox.ERROR_CODE, resultCode)
|
||||
}
|
||||
context.contentResolver.update(Sms.Outbox.CONTENT_URI, values, "_id=$id", null)
|
||||
query.close()
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateAppDatabase(context: Context, intent: Intent, receiverResultCode: Int) {
|
||||
val uri = intent.data
|
||||
if (uri != null) {
|
||||
val messageId = uri.lastPathSegment?.toLong() ?: 0L
|
||||
ensureBackgroundThread {
|
||||
val type = if (receiverResultCode == Activity.RESULT_OK) {
|
||||
Telephony.Sms.MESSAGE_TYPE_SENT
|
||||
Sms.MESSAGE_TYPE_SENT
|
||||
} else {
|
||||
showSendingFailedNotification(context, messageId)
|
||||
Telephony.Sms.MESSAGE_TYPE_FAILED
|
||||
Sms.MESSAGE_TYPE_FAILED
|
||||
}
|
||||
|
||||
context.updateMessageType(messageId, type)
|
||||
val updated = context.messagesDB.updateType(messageId, type)
|
||||
if (updated == 0) {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
|
Reference in New Issue
Block a user