fix: improve sms receiver handling (#642)
* fix: improve sms receiver handling * docs: add comment regarding multiple messages * fix: catch errors when inserting conversation Refs: https://github.com/FossifyOrg/Messages/issues/159
This commit is contained in:
parent
ed2aedd915
commit
1e3f5e5933
4 changed files with 138 additions and 119 deletions
|
|
@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Fixed
|
||||||
|
- Fixed missing notifications in some cases ([#159])
|
||||||
|
|
||||||
## [1.7.0] - 2025-12-16
|
## [1.7.0] - 2025-12-16
|
||||||
### Added
|
### Added
|
||||||
|
|
@ -188,6 +190,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
[#115]: https://github.com/FossifyOrg/Messages/issues/115
|
[#115]: https://github.com/FossifyOrg/Messages/issues/115
|
||||||
[#135]: https://github.com/FossifyOrg/Messages/issues/135
|
[#135]: https://github.com/FossifyOrg/Messages/issues/135
|
||||||
[#153]: https://github.com/FossifyOrg/Messages/issues/153
|
[#153]: https://github.com/FossifyOrg/Messages/issues/153
|
||||||
|
[#159]: https://github.com/FossifyOrg/Messages/issues/159
|
||||||
[#165]: https://github.com/FossifyOrg/Messages/issues/165
|
[#165]: https://github.com/FossifyOrg/Messages/issues/165
|
||||||
[#177]: https://github.com/FossifyOrg/Messages/issues/177
|
[#177]: https://github.com/FossifyOrg/Messages/issues/177
|
||||||
[#180]: https://github.com/FossifyOrg/Messages/issues/180
|
[#180]: https://github.com/FossifyOrg/Messages/issues/180
|
||||||
|
|
|
||||||
|
|
@ -1050,14 +1050,11 @@ fun Context.getThreadId(addresses: Set<String>): Long {
|
||||||
fun Context.showReceivedMessageNotification(
|
fun Context.showReceivedMessageNotification(
|
||||||
messageId: Long,
|
messageId: Long,
|
||||||
address: String,
|
address: String,
|
||||||
|
senderName: String,
|
||||||
body: String,
|
body: String,
|
||||||
threadId: Long,
|
threadId: Long,
|
||||||
bitmap: Bitmap?,
|
bitmap: Bitmap?,
|
||||||
) {
|
) {
|
||||||
val privateCursor = getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
|
|
||||||
ensureBackgroundThread {
|
|
||||||
val senderName = getNameFromAddress(address, privateCursor)
|
|
||||||
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
notificationHelper.showMessageNotification(
|
notificationHelper.showMessageNotification(
|
||||||
messageId = messageId,
|
messageId = messageId,
|
||||||
|
|
@ -1069,7 +1066,6 @@ fun Context.showReceivedMessageNotification(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.getNameFromAddress(address: String, privateCursor: Cursor?): String {
|
fun Context.getNameFromAddress(address: String, privateCursor: Cursor?): String {
|
||||||
var sender = getNameAndPhotoFromPhoneNumber(address).name
|
var sender = getNameAndPhotoFromPhoneNumber(address).name
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ package org.fossify.messages.receivers
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.klinker.android.send_message.MmsReceivedReceiver
|
import com.klinker.android.send_message.MmsReceivedReceiver
|
||||||
import org.fossify.commons.extensions.baseConfig
|
import org.fossify.commons.extensions.baseConfig
|
||||||
|
|
@ -16,6 +14,7 @@ import org.fossify.commons.helpers.ensureBackgroundThread
|
||||||
import org.fossify.messages.R
|
import org.fossify.messages.R
|
||||||
import org.fossify.messages.extensions.getConversations
|
import org.fossify.messages.extensions.getConversations
|
||||||
import org.fossify.messages.extensions.getLatestMMS
|
import org.fossify.messages.extensions.getLatestMMS
|
||||||
|
import org.fossify.messages.extensions.getNameFromAddress
|
||||||
import org.fossify.messages.extensions.insertOrUpdateConversation
|
import org.fossify.messages.extensions.insertOrUpdateConversation
|
||||||
import org.fossify.messages.extensions.shouldUnarchive
|
import org.fossify.messages.extensions.shouldUnarchive
|
||||||
import org.fossify.messages.extensions.showReceivedMessageNotification
|
import org.fossify.messages.extensions.showReceivedMessageNotification
|
||||||
|
|
@ -31,13 +30,11 @@ class MmsReceiver : MmsReceivedReceiver() {
|
||||||
val normalizedAddress = address.normalizePhoneNumber()
|
val normalizedAddress = address.normalizePhoneNumber()
|
||||||
if (context.isNumberBlocked(normalizedAddress)) return true
|
if (context.isNumberBlocked(normalizedAddress)) return true
|
||||||
if (context.baseConfig.blockUnknownNumbers) {
|
if (context.baseConfig.blockUnknownNumbers) {
|
||||||
val privateCursor = context.getMyContactsCursor(
|
context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true).use {
|
||||||
favoritesOnly = false,
|
val isKnownContact = SimpleContactsHelper(context).existsSync(address, it)
|
||||||
withPhoneNumbersOnly = true
|
|
||||||
)
|
|
||||||
val isKnownContact = SimpleContactsHelper(context).existsSync(address, privateCursor)
|
|
||||||
return !isKnownContact
|
return !isKnownContact
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -76,19 +73,22 @@ class MmsReceiver : MmsReceivedReceiver() {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
|
||||||
|
val senderName = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true).use {
|
||||||
|
context.getNameFromAddress(address, it)
|
||||||
|
}
|
||||||
|
|
||||||
context.showReceivedMessageNotification(
|
context.showReceivedMessageNotification(
|
||||||
messageId = mms.id,
|
messageId = mms.id,
|
||||||
address = address,
|
address = address,
|
||||||
|
senderName = senderName,
|
||||||
body = mms.body,
|
body = mms.body,
|
||||||
threadId = mms.threadId,
|
threadId = mms.threadId,
|
||||||
bitmap = glideBitmap
|
bitmap = glideBitmap
|
||||||
)
|
)
|
||||||
|
|
||||||
ensureBackgroundThread {
|
val conversation = context.getConversations(mms.threadId).firstOrNull() ?: return
|
||||||
val conversation = context.getConversations(mms.threadId).firstOrNull()
|
runCatching { context.insertOrUpdateConversation(conversation) }
|
||||||
?: return@ensureBackgroundThread
|
|
||||||
context.insertOrUpdateConversation(conversation)
|
|
||||||
if (context.shouldUnarchive()) {
|
if (context.shouldUnarchive()) {
|
||||||
context.updateConversationArchivedStatus(mms.threadId, false)
|
context.updateConversationArchivedStatus(mms.threadId, false)
|
||||||
}
|
}
|
||||||
|
|
@ -96,5 +96,3 @@ class MmsReceiver : MmsReceivedReceiver() {
|
||||||
refreshConversations()
|
refreshConversations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ package org.fossify.messages.receivers
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.provider.Telephony
|
import android.provider.Telephony
|
||||||
import org.fossify.commons.extensions.baseConfig
|
import org.fossify.commons.extensions.baseConfig
|
||||||
import org.fossify.commons.extensions.getMyContactsCursor
|
import org.fossify.commons.extensions.getMyContactsCursor
|
||||||
|
|
@ -29,104 +27,128 @@ import org.fossify.messages.helpers.refreshMessages
|
||||||
import org.fossify.messages.models.Message
|
import org.fossify.messages.models.Message
|
||||||
|
|
||||||
class SmsReceiver : BroadcastReceiver() {
|
class SmsReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val messages = Telephony.Sms.Intents.getMessagesFromIntent(intent)
|
val pending = goAsync()
|
||||||
var address = ""
|
val appContext = context.applicationContext
|
||||||
var body = ""
|
|
||||||
var subject = ""
|
ensureBackgroundThread {
|
||||||
var date = 0L
|
try {
|
||||||
var threadId = 0L
|
val parts = Telephony.Sms.Intents.getMessagesFromIntent(intent)
|
||||||
var status = Telephony.Sms.STATUS_NONE
|
if (parts.isEmpty()) return@ensureBackgroundThread
|
||||||
val type = Telephony.Sms.MESSAGE_TYPE_INBOX
|
|
||||||
val read = 0
|
// this is how it has always worked, but need to revisit this.
|
||||||
|
val address = parts.last().originatingAddress.orEmpty()
|
||||||
|
if (address.isBlank()) return@ensureBackgroundThread
|
||||||
|
val subject = parts.last().pseudoSubject.orEmpty()
|
||||||
|
val status = parts.last().status
|
||||||
|
val body = buildString { parts.forEach { append(it.messageBody.orEmpty()) } }
|
||||||
|
|
||||||
|
if (isMessageFilteredOut(appContext, body)) return@ensureBackgroundThread
|
||||||
|
if (appContext.isNumberBlocked(address)) return@ensureBackgroundThread
|
||||||
|
if (appContext.baseConfig.blockUnknownNumbers) {
|
||||||
|
appContext.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true).use {
|
||||||
|
val isKnownContact = SimpleContactsHelper(appContext).existsSync(address, it)
|
||||||
|
if (!isKnownContact) return@ensureBackgroundThread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val date = System.currentTimeMillis()
|
||||||
|
val threadId = appContext.getThreadId(address)
|
||||||
val subscriptionId = intent.getIntExtra("subscription", -1)
|
val subscriptionId = intent.getIntExtra("subscription", -1)
|
||||||
|
|
||||||
val privateCursor = context.getMyContactsCursor(false, true)
|
handleMessageSync(
|
||||||
ensureBackgroundThread {
|
context = appContext,
|
||||||
messages.forEach {
|
address = address,
|
||||||
address = it.originatingAddress ?: ""
|
subject = subject,
|
||||||
subject = it.pseudoSubject
|
body = body,
|
||||||
status = it.status
|
date = date,
|
||||||
body += it.messageBody
|
threadId = threadId,
|
||||||
date = System.currentTimeMillis()
|
subscriptionId = subscriptionId,
|
||||||
threadId = context.getThreadId(address)
|
status = status
|
||||||
}
|
)
|
||||||
if (context.baseConfig.blockUnknownNumbers) {
|
} finally {
|
||||||
val simpleContactsHelper = SimpleContactsHelper(context)
|
pending.finish()
|
||||||
// Maybe switch to existsSync()? No?
|
|
||||||
simpleContactsHelper.exists(address, privateCursor) { exists ->
|
|
||||||
if (exists) {
|
|
||||||
handleMessage(context, address, subject, body, date, read, threadId, type, subscriptionId, status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
handleMessage(context, address, subject, body, date, read, threadId, type, subscriptionId, status)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleMessage(
|
private fun handleMessageSync(
|
||||||
context: Context,
|
context: Context,
|
||||||
address: String,
|
address: String,
|
||||||
subject: String,
|
subject: String,
|
||||||
body: String,
|
body: String,
|
||||||
date: Long,
|
date: Long,
|
||||||
read: Int,
|
read: Int = 0,
|
||||||
threadId: Long,
|
threadId: Long,
|
||||||
type: Int,
|
type: Int = Telephony.Sms.MESSAGE_TYPE_INBOX,
|
||||||
subscriptionId: Int,
|
subscriptionId: Int,
|
||||||
status: Int
|
status: Int
|
||||||
) {
|
) {
|
||||||
if (isMessageFilteredOut(context, body)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address)
|
val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address)
|
||||||
val bitmap = context.getNotificationBitmap(photoUri)
|
val bitmap = context.getNotificationBitmap(photoUri)
|
||||||
Handler(Looper.getMainLooper()).post {
|
|
||||||
if (!context.isNumberBlocked(address)) {
|
|
||||||
val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
|
|
||||||
ensureBackgroundThread {
|
|
||||||
val newMessageId = context.insertNewSMS(address, subject, body, date, read, threadId, type, subscriptionId)
|
|
||||||
|
|
||||||
val conversation = context.getConversations(threadId).firstOrNull() ?: return@ensureBackgroundThread
|
val newMessageId = context.insertNewSMS(
|
||||||
try {
|
address = address,
|
||||||
context.insertOrUpdateConversation(conversation)
|
subject = subject,
|
||||||
} catch (ignored: Exception) {
|
body = body,
|
||||||
|
date = date,
|
||||||
|
read = read,
|
||||||
|
threadId = threadId,
|
||||||
|
type = type,
|
||||||
|
subscriptionId = subscriptionId
|
||||||
|
)
|
||||||
|
|
||||||
|
context.getConversations(threadId).firstOrNull()?.let { conv ->
|
||||||
|
runCatching { context.insertOrUpdateConversation(conv) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val senderName = context.getNameFromAddress(address, privateCursor)
|
val senderName = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true).use {
|
||||||
val phoneNumber = PhoneNumber(address, 0, "", address)
|
context.getNameFromAddress(address, it)
|
||||||
val participant = SimpleContact(0, 0, senderName, photoUri, arrayListOf(phoneNumber), ArrayList(), ArrayList())
|
}
|
||||||
val participants = arrayListOf(participant)
|
|
||||||
val messageDate = (date / 1000).toInt()
|
|
||||||
|
|
||||||
val message =
|
val participant = SimpleContact(
|
||||||
Message(
|
rawId = 0,
|
||||||
newMessageId,
|
contactId = 0,
|
||||||
body,
|
name = senderName,
|
||||||
type,
|
photoUri = photoUri,
|
||||||
status,
|
phoneNumbers = arrayListOf(PhoneNumber(value = address, type = 0, label = "", normalizedNumber = address)),
|
||||||
participants,
|
birthdays = ArrayList(),
|
||||||
messageDate,
|
anniversaries = ArrayList()
|
||||||
false,
|
|
||||||
threadId,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
address,
|
|
||||||
senderName,
|
|
||||||
photoUri,
|
|
||||||
subscriptionId
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val message = Message(
|
||||||
|
id = newMessageId,
|
||||||
|
body = body,
|
||||||
|
type = type,
|
||||||
|
status = status,
|
||||||
|
participants = arrayListOf(participant),
|
||||||
|
date = (date / 1000).toInt(),
|
||||||
|
read = false,
|
||||||
|
threadId = threadId,
|
||||||
|
isMMS = false,
|
||||||
|
attachment = null,
|
||||||
|
senderPhoneNumber = address,
|
||||||
|
senderName = senderName,
|
||||||
|
senderPhotoUri = photoUri,
|
||||||
|
subscriptionId = subscriptionId
|
||||||
|
)
|
||||||
|
|
||||||
context.messagesDB.insertOrUpdate(message)
|
context.messagesDB.insertOrUpdate(message)
|
||||||
|
|
||||||
if (context.shouldUnarchive()) {
|
if (context.shouldUnarchive()) {
|
||||||
context.updateConversationArchivedStatus(threadId, false)
|
context.updateConversationArchivedStatus(threadId, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshMessages()
|
refreshMessages()
|
||||||
refreshConversations()
|
refreshConversations()
|
||||||
context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap)
|
context.showReceivedMessageNotification(
|
||||||
}
|
messageId = newMessageId,
|
||||||
}
|
address = address,
|
||||||
}
|
senderName = senderName,
|
||||||
|
body = body,
|
||||||
|
threadId = threadId,
|
||||||
|
bitmap = bitmap
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue