From 7554bb1f10f4105a050bc405036ef928a7e17411 Mon Sep 17 00:00:00 2001 From: tibbi Date: Fri, 1 Jan 2021 22:52:23 +0100 Subject: [PATCH] show a notification if a message sending failed --- .../smsmessenger/extensions/Context.kt | 40 ++++++-- .../receivers/SmsStatusSentReceiver.kt | 94 +++++++++++++++++-- 2 files changed, 122 insertions(+), 12 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt index 6aef8cc6..b30cf279 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt @@ -8,6 +8,7 @@ import android.app.PendingIntent import android.content.ContentValues import android.content.Context import android.content.Intent +import android.database.Cursor import android.graphics.Bitmap import android.media.AudioAttributes import android.media.AudioManager @@ -320,6 +321,28 @@ fun Context.getThreadSnippet(threadId: Long): String { return snippet } +fun Context.getMessageRecipientAddress(messageId: Long): String { + val uri = Sms.CONTENT_URI + val projection = arrayOf( + Sms.ADDRESS + ) + + val selection = "${Sms._ID} = ?" + val selectionArgs = arrayOf(messageId.toString()) + + try { + val cursor = contentResolver.query(uri, projection, selection, selectionArgs, null) + cursor?.use { + if (cursor.moveToFirst()) { + return cursor.getStringValue(Sms.ADDRESS) + } + } + } catch (e: Exception) { + } + + return "" +} + fun Context.getThreadParticipants(threadId: Long, contactsMap: HashMap?): ArrayList { val uri = Uri.parse("${MmsSms.CONTENT_CONVERSATIONS_URI}?simple=true") val projection = arrayOf( @@ -612,18 +635,23 @@ fun Context.getThreadId(addresses: Set): Long { fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) { val privateCursor = getMyContactsCursor()?.loadInBackground() ensureBackgroundThread { - var sender = getNameAndPhotoFromPhoneNumber(address).name - if (address == sender) { - val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor) - sender = privateContacts.firstOrNull { it.doesContainPhoneNumber(address) }?.name ?: address - } + val senderName = getNameFromAddress(address, privateCursor) Handler(Looper.getMainLooper()).post { - showMessageNotification(address, body, threadId, bitmap, sender) + showMessageNotification(address, body, threadId, bitmap, senderName) } } } +fun Context.getNameFromAddress(address: String, privateCursor: Cursor?): String { + var sender = getNameAndPhotoFromPhoneNumber(address).name + if (address == sender) { + val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor) + sender = privateContacts.firstOrNull { it.doesContainPhoneNumber(address) }?.name ?: address + } + return sender +} + @SuppressLint("NewApi") fun Context.showMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?, sender: String) { val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt index cb2164d5..6f7451f6 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsStatusSentReceiver.kt @@ -1,13 +1,30 @@ package com.simplemobiletools.smsmessenger.receivers +import android.annotation.SuppressLint +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.media.AudioAttributes +import android.media.AudioManager +import android.media.RingtoneManager import android.net.Uri +import android.os.Handler +import android.os.Looper import android.provider.Telephony +import androidx.core.app.NotificationCompat +import com.simplemobiletools.commons.extensions.getMyContactsCursor +import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.ensureBackgroundThread -import com.simplemobiletools.smsmessenger.extensions.messagesDB -import com.simplemobiletools.smsmessenger.extensions.updateMessageType +import com.simplemobiletools.commons.helpers.isOreoPlus +import com.simplemobiletools.smsmessenger.R +import com.simplemobiletools.smsmessenger.activities.ThreadActivity +import com.simplemobiletools.smsmessenger.extensions.* +import com.simplemobiletools.smsmessenger.helpers.NOTIFICATION_CHANNEL +import com.simplemobiletools.smsmessenger.helpers.THREAD_ID import com.simplemobiletools.smsmessenger.helpers.refreshMessages class SmsStatusSentReceiver : BroadcastReceiver() { @@ -15,13 +32,78 @@ class SmsStatusSentReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.extras?.containsKey("message_uri") == true) { val uri = Uri.parse(intent.getStringExtra("message_uri")) - val id = uri?.lastPathSegment?.toLong() ?: 0L + val messageId = uri?.lastPathSegment?.toLong() ?: 0L ensureBackgroundThread { - val type = if (intent.extras!!.containsKey("errorCode")) Telephony.Sms.MESSAGE_TYPE_FAILED else Telephony.Sms.MESSAGE_TYPE_OUTBOX - context.updateMessageType(id, type) - context.messagesDB.updateType(id, type) + val type = if (intent.extras!!.containsKey("errorCode")) { + showSendingFailedNotification(context, messageId) + Telephony.Sms.MESSAGE_TYPE_FAILED + } else { + Telephony.Sms.MESSAGE_TYPE_OUTBOX + } + context.updateMessageType(messageId, type) + context.messagesDB.updateType(messageId, type) refreshMessages() } } } + + private fun showSendingFailedNotification(context: Context, messageId: Long) { + Handler(Looper.getMainLooper()).post { + val privateCursor = context.getMyContactsCursor()?.loadInBackground() + ensureBackgroundThread { + val address = context.getMessageRecipientAddress(messageId) + val threadId = context.getThreadId(address) + val senderName = context.getNameFromAddress(address, privateCursor) + showNotification(context, senderName, threadId) + } + } + } + + @SuppressLint("NewApi") + private fun showNotification(context: Context, recipientName: String, threadId: Long) { + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) + if (isOreoPlus()) { + val audioAttributes = AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_NOTIFICATION) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setLegacyStreamType(AudioManager.STREAM_NOTIFICATION) + .build() + + val name = context.getString(R.string.message_not_sent_short) + val importance = NotificationManager.IMPORTANCE_HIGH + NotificationChannel(NOTIFICATION_CHANNEL, name, importance).apply { + setBypassDnd(false) + enableLights(true) + setSound(soundUri, audioAttributes) + enableVibration(true) + notificationManager.createNotificationChannel(this) + } + } + + val intent = Intent(context, ThreadActivity::class.java).apply { + putExtra(THREAD_ID, threadId) + } + + val pendingIntent = PendingIntent.getActivity(context, threadId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT) + val summaryText = String.format(context.getString(R.string.message_sending_error), recipientName) + + val largeIcon = SimpleContactsHelper(context).getContactLetterIcon(recipientName) + val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL) + .setContentTitle(context.getString(R.string.message_not_sent_short)) + .setContentText(summaryText) + .setColor(context.config.primaryColor) + .setSmallIcon(R.drawable.ic_messenger) + .setLargeIcon(largeIcon) + .setStyle(NotificationCompat.BigTextStyle().bigText(summaryText)) + .setContentIntent(pendingIntent) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setDefaults(Notification.DEFAULT_LIGHTS) + .setCategory(Notification.CATEGORY_MESSAGE) + .setAutoCancel(true) + .setSound(soundUri, AudioManager.STREAM_NOTIFICATION) + .setChannelId(NOTIFICATION_CHANNEL) + + notificationManager.notify(threadId.hashCode(), builder.build()) + } }