Show 2 checks when sms is delivered

- differentiate between sent sms and delivered sms by updating the SmsStatusSentReceiver which updates the type to Telephony.Sms.MESSAGE_TYPE_SENT or Telephony.Sms.MESSAGE_TYPE_FAILED depending on the outcome.
- rename ThreadSuccess to ThreadSent and add a boolean field for the delivery status
- SmsStatusSentReceiver updates the status of the message to Telephony.Sms.STATUS_COMPLETE.
- accommodate for the need to keep track of the status by adding Int field status to the Message class,
- add appropriate database migrations (3 to 4) for the new status field.
- add status to the query for sms in extension function Context.getMessages and Context.getMMS
- add extension function Context.updateMessageStatus to update the status of a message in the database
This commit is contained in:
Paul Akhamiogu 2021-08-25 16:57:07 +01:00
parent 84c1705078
commit 46f71c994f
13 changed files with 58 additions and 27 deletions

View File

@ -569,8 +569,8 @@ class ThreadActivity : SimpleActivity() {
conversationsDB.markRead(threadId)
}
if (i == cnt - 1 && message.type == Telephony.Sms.MESSAGE_TYPE_SENT) {
items.add(ThreadSuccess(message.id))
if (i == cnt - 1 && (message.type == Telephony.Sms.MESSAGE_TYPE_SENT )) {
items.add(ThreadSent(message.id, delivered = message.status == Telephony.Sms.STATUS_COMPLETE))
}
}

View File

@ -99,7 +99,7 @@ class ThreadAdapter(
THREAD_DATE_TIME -> R.layout.item_thread_date_time
THREAD_RECEIVED_MESSAGE -> R.layout.item_received_message
THREAD_SENT_MESSAGE_ERROR -> R.layout.item_thread_error
THREAD_SENT_MESSAGE_SUCCESS -> R.layout.item_thread_success
THREAD_SENT_MESSAGE_SENT -> R.layout.item_thread_success
THREAD_SENT_MESSAGE_SENDING -> R.layout.item_thread_sending
else -> R.layout.item_sent_message
}
@ -113,7 +113,7 @@ class ThreadAdapter(
holder.bindView(item, isClickable, isLongClickable) { itemView, layoutPosition ->
when (item) {
is ThreadDateTime -> setupDateTime(itemView, item)
is ThreadSuccess -> setupThreadSuccess(itemView)
is ThreadSent -> setupThreadSuccess(itemView, item.delivered)
is ThreadError -> setupThreadError(itemView)
is ThreadSending -> setupThreadSending(itemView)
else -> setupView(itemView, item as Message)
@ -130,7 +130,7 @@ class ThreadAdapter(
item is ThreadDateTime -> THREAD_DATE_TIME
(messages[position] as? Message)?.isReceivedMessage() == true -> THREAD_RECEIVED_MESSAGE
item is ThreadError -> THREAD_SENT_MESSAGE_ERROR
item is ThreadSuccess -> THREAD_SENT_MESSAGE_SUCCESS
item is ThreadSent -> THREAD_SENT_MESSAGE_SENT
item is ThreadSending -> THREAD_SENT_MESSAGE_SENDING
else -> THREAD_SENT_MESSAGE
}
@ -350,7 +350,8 @@ class ThreadAdapter(
}
}
private fun setupThreadSuccess(view: View) {
private fun setupThreadSuccess(view: View, isDelivered: Boolean = false) {
view.thread_success.setImageResource(if (isDelivered) R.drawable.ic_check_double_vector else R.drawable.ic_check_vector)
view.thread_success.applyColorFilter(textColor)
}

View File

@ -17,7 +17,7 @@ import com.simplemobiletools.smsmessenger.models.Conversation
import com.simplemobiletools.smsmessenger.models.Message
import com.simplemobiletools.smsmessenger.models.MessageAttachment
@Database(entities = [Conversation::class, Attachment::class, MessageAttachment::class, Message::class], version = 3)
@Database(entities = [Conversation::class, Attachment::class, MessageAttachment::class, Message::class], version = 4)
@TypeConverters(Converters::class)
abstract class MessagesDatabase : RoomDatabase() {
@ -40,6 +40,7 @@ abstract class MessagesDatabase : RoomDatabase() {
.fallbackToDestructiveMigration()
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
.addMigrations(MIGRATION_3_4)
.build()
}
}
@ -76,5 +77,13 @@ abstract class MessagesDatabase : RoomDatabase() {
}
}
}
private val MIGRATION_3_4 = object : Migration(3, 4) {
override fun migrate(database: SupportSQLiteDatabase) {
database.apply {
execSQL("ALTER TABLE messages ADD COLUMN status INTEGER NOT NULL DEFAULT -1")
}
}
}
}
}

View File

@ -35,9 +35,9 @@ import com.simplemobiletools.smsmessenger.interfaces.MessagesDao
import com.simplemobiletools.smsmessenger.models.*
import com.simplemobiletools.smsmessenger.receivers.DirectReplyReceiver
import com.simplemobiletools.smsmessenger.receivers.MarkAsReadReceiver
import me.leolin.shortcutbadger.ShortcutBadger
import java.util.*
import kotlin.collections.ArrayList
import me.leolin.shortcutbadger.ShortcutBadger
val Context.config: Config get() = Config.newInstance(applicationContext)
@ -61,7 +61,8 @@ fun Context.getMessages(threadId: Long): ArrayList<Message> {
Sms.DATE,
Sms.READ,
Sms.THREAD_ID,
Sms.SUBSCRIPTION_ID
Sms.SUBSCRIPTION_ID,
Sms.STATUS
)
val selection = "${Sms.THREAD_ID} = ?"
@ -96,9 +97,10 @@ fun Context.getMessages(threadId: Long): ArrayList<Message> {
val read = cursor.getIntValue(Sms.READ) == 1
val thread = cursor.getLongValue(Sms.THREAD_ID)
val subscriptionId = cursor.getIntValue(Sms.SUBSCRIPTION_ID)
val status = cursor.getIntValue(Sms.STATUS)
val participant = SimpleContact(0, 0, senderName, photoUri, arrayListOf(senderNumber), ArrayList(), ArrayList())
val isMMS = false
val message = Message(id, body, type, arrayListOf(participant), date, read, thread, isMMS, null, senderName, photoUri, subscriptionId)
val message = Message(id, body, type, status, arrayListOf(participant), date, read, thread, isMMS, null, senderName, photoUri, subscriptionId)
messages.add(message)
}
@ -118,7 +120,8 @@ fun Context.getMMS(threadId: Long? = null, sortOrder: String? = null): ArrayList
Mms.READ,
Mms.MESSAGE_BOX,
Mms.THREAD_ID,
Mms.SUBSCRIPTION_ID
Mms.SUBSCRIPTION_ID,
Mms.STATUS
)
val selection = if (threadId == null) {
@ -143,6 +146,7 @@ fun Context.getMMS(threadId: Long? = null, sortOrder: String? = null): ArrayList
val read = cursor.getIntValue(Mms.READ) == 1
val threadId = cursor.getLongValue(Mms.THREAD_ID)
val subscriptionId = cursor.getIntValue(Mms.SUBSCRIPTION_ID)
val status = cursor.getIntValue(Mms.STATUS)
val participants = if (threadParticipants.containsKey(threadId)) {
threadParticipants[threadId]!!
} else {
@ -164,7 +168,7 @@ fun Context.getMMS(threadId: Long? = null, sortOrder: String? = null): ArrayList
senderPhotoUri = namePhoto.photoUri ?: ""
}
val message = Message(mmsId, body, type, participants, date, read, threadId, isMMS, attachment, senderName, senderPhotoUri, subscriptionId)
val message = Message(mmsId, body, type, status, participants, date, read, threadId, isMMS, attachment, senderName, senderPhotoUri, subscriptionId)
messages.add(message)
participants.forEach {
@ -580,10 +584,20 @@ fun Context.markThreadMessagesUnread(threadId: Long) {
}
}
fun Context.updateMessageType(id: Long, status: Int) {
fun Context.updateMessageType(id: Long, type: Int) {
val uri = Sms.CONTENT_URI
val contentValues = ContentValues().apply {
put(Sms.TYPE, status)
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())

View File

@ -24,7 +24,7 @@ const val THREAD_DATE_TIME = 1
const val THREAD_RECEIVED_MESSAGE = 2
const val THREAD_SENT_MESSAGE = 3
const val THREAD_SENT_MESSAGE_ERROR = 4
const val THREAD_SENT_MESSAGE_SUCCESS = 5
const val THREAD_SENT_MESSAGE_SENT = 5
const val THREAD_SENT_MESSAGE_SENDING = 6
// lock screen visibility constants

View File

@ -35,6 +35,9 @@ interface MessagesDao {
@Query("UPDATE messages SET type = :type WHERE id = :id")
fun updateType(id: Long, type: Int): Int
@Query("UPDATE messages SET status = :status WHERE id = :id")
fun updateStatus(id: Long, status: Int): Int
@Query("DELETE FROM messages WHERE id = :id")
fun delete(id: Long)

View File

@ -11,6 +11,7 @@ data class Message(
@PrimaryKey val id: Long,
@ColumnInfo(name = "body") val body: String,
@ColumnInfo(name = "type") val type: Int,
@ColumnInfo(name = "status") val status: Int,
@ColumnInfo(name = "participants") val participants: ArrayList<SimpleContact>,
@ColumnInfo(name = "date") val date: Int,
@ColumnInfo(name = "read") val read: Boolean,

View File

@ -0,0 +1,5 @@
package com.simplemobiletools.smsmessenger.models
// show a check after the latest message, if it is a sent one and succeeded,
// show a double check if it is delivered
data class ThreadSent(val messageID: Long, val delivered: Boolean) : ThreadItem()

View File

@ -1,4 +0,0 @@
package com.simplemobiletools.smsmessenger.models
// show a check after the latest message, if it is a sent one and succeeded
data class ThreadSuccess(val messageID: Long) : ThreadItem()

View File

@ -21,6 +21,7 @@ class SmsReceiver : BroadcastReceiver() {
var subject = ""
var date = 0L
var threadId = 0L
var status = Telephony.Sms.STATUS_NONE
val type = Telephony.Sms.MESSAGE_TYPE_INBOX
val read = 0
val subscriptionId = intent.getIntExtra("subscription", -1)
@ -29,6 +30,7 @@ class SmsReceiver : BroadcastReceiver() {
messages.forEach {
address = it.originatingAddress ?: ""
subject = it.pseudoSubject
status = it.status
body += it.messageBody
date = Math.min(it.timestampMillis, System.currentTimeMillis())
threadId = context.getThreadId(address)
@ -49,7 +51,7 @@ class SmsReceiver : BroadcastReceiver() {
val participant = SimpleContact(0, 0, address, "", arrayListOf(address), ArrayList(), ArrayList())
val participants = arrayListOf(participant)
val messageDate = (date / 1000).toInt()
val message = Message(newMessageId, body, type, participants, messageDate, false, threadId, false, null, address, "", subscriptionId)
val message = Message(newMessageId, body, type, status, participants, messageDate, false, threadId, false, null, address, "", subscriptionId)
context.messagesDB.insertOrUpdate(message)
refreshMessages()
}

View File

@ -9,7 +9,7 @@ import android.provider.Telephony
import com.klinker.android.send_message.DeliveredReceiver
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.smsmessenger.extensions.messagesDB
import com.simplemobiletools.smsmessenger.extensions.updateMessageType
import com.simplemobiletools.smsmessenger.extensions.updateMessageStatus
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
class SmsStatusDeliveredReceiver : DeliveredReceiver() {
@ -19,13 +19,13 @@ class SmsStatusDeliveredReceiver : DeliveredReceiver() {
val uri = Uri.parse(intent.getStringExtra("message_uri"))
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
ensureBackgroundThread {
val type = Telephony.Sms.MESSAGE_TYPE_SENT
context.updateMessageType(messageId, type)
val updated = context.messagesDB.updateType(messageId, type)
val status = Telephony.Sms.STATUS_COMPLETE
context.updateMessageStatus(messageId, status)
val updated = context.messagesDB.updateStatus(messageId, status)
if (updated == 0) {
Handler(Looper.getMainLooper()).postDelayed({
ensureBackgroundThread {
context.messagesDB.updateType(messageId, type)
context.messagesDB.updateStatus(messageId, status)
}
}, 2000)
}

View File

@ -39,7 +39,7 @@ class SmsStatusSentReceiver : SentReceiver() {
showSendingFailedNotification(context, messageId)
Telephony.Sms.MESSAGE_TYPE_FAILED
} else {
Telephony.Sms.MESSAGE_TYPE_OUTBOX
Telephony.Sms.MESSAGE_TYPE_SENT
}
context.updateMessageType(messageId, type)

View File

@ -46,7 +46,7 @@
<!-- Settings -->
<string name="lock_screen_visibility">Meldingen op vergrendelscherm</string>
<string name="sender_and_message">Afzender en bericht/string>
<string name="sender_and_message">Afzender en bericht</string>
<string name="sender_only">Alleen afzender</string>
<string name="enable_delivery_reports">Bezorgingsrapporten inschakelen</string>