mirror of
https://github.com/SimpleMobileTools/Simple-SMS-Messenger.git
synced 2025-02-20 13:40:51 +01:00
Merge pull request #520 from Naveen3Singh/notification_improvements
Improve and organise notification related code
This commit is contained in:
commit
7ea57de52b
@ -70,6 +70,7 @@ dependencies {
|
|||||||
implementation "me.leolin:ShortcutBadger:1.1.22"
|
implementation "me.leolin:ShortcutBadger:1.1.22"
|
||||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||||
implementation 'com.googlecode.ez-vcard:ez-vcard:0.11.3'
|
implementation 'com.googlecode.ez-vcard:ez-vcard:0.11.3'
|
||||||
|
implementation 'androidx.lifecycle:lifecycle-process:2.5.1'
|
||||||
|
|
||||||
kapt "androidx.room:room-compiler:2.4.3"
|
kapt "androidx.room:room-compiler:2.4.3"
|
||||||
implementation "androidx.room:room-runtime:2.4.3"
|
implementation "androidx.room:room-runtime:2.4.3"
|
||||||
|
@ -89,15 +89,18 @@ class MainActivity : SimpleActivity() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
setupToolbar(main_toolbar)
|
setupToolbar(main_toolbar)
|
||||||
|
|
||||||
|
getOrCreateConversationsAdapter().apply {
|
||||||
if (storedTextColor != getProperTextColor()) {
|
if (storedTextColor != getProperTextColor()) {
|
||||||
(conversations_list.adapter as? ConversationsAdapter)?.updateTextColor(getProperTextColor())
|
updateTextColor(getProperTextColor())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (storedFontSize != config.fontSize) {
|
if (storedFontSize != config.fontSize) {
|
||||||
(conversations_list.adapter as? ConversationsAdapter)?.updateFontSize()
|
updateFontSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDrafts()
|
||||||
}
|
}
|
||||||
|
|
||||||
(conversations_list.adapter as? ConversationsAdapter)?.updateDrafts()
|
|
||||||
updateTextColors(main_coordinator)
|
updateTextColors(main_coordinator)
|
||||||
|
|
||||||
val properPrimaryColor = getProperPrimaryColor()
|
val properPrimaryColor = getProperPrimaryColor()
|
||||||
@ -285,6 +288,25 @@ class MainActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getOrCreateConversationsAdapter(): ConversationsAdapter {
|
||||||
|
var currAdapter = conversations_list.adapter
|
||||||
|
if (currAdapter == null) {
|
||||||
|
hideKeyboard()
|
||||||
|
currAdapter = ConversationsAdapter(
|
||||||
|
activity = this,
|
||||||
|
recyclerView = conversations_list,
|
||||||
|
onRefresh = { notifyDatasetChanged() },
|
||||||
|
itemClick = { handleConversationClick(it) }
|
||||||
|
)
|
||||||
|
|
||||||
|
conversations_list.adapter = currAdapter
|
||||||
|
if (areSystemAnimationsEnabled) {
|
||||||
|
conversations_list.scheduleLayoutAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currAdapter as ConversationsAdapter
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupConversations(conversations: ArrayList<Conversation>) {
|
private fun setupConversations(conversations: ArrayList<Conversation>) {
|
||||||
val hasConversations = conversations.isNotEmpty()
|
val hasConversations = conversations.isNotEmpty()
|
||||||
val sortedConversations = conversations.sortedWith(
|
val sortedConversations = conversations.sortedWith(
|
||||||
@ -301,37 +323,33 @@ class MainActivity : SimpleActivity() {
|
|||||||
no_conversations_placeholder_2.beGone()
|
no_conversations_placeholder_2.beGone()
|
||||||
}
|
}
|
||||||
|
|
||||||
val currAdapter = conversations_list.adapter
|
|
||||||
if (currAdapter == null) {
|
|
||||||
hideKeyboard()
|
|
||||||
ConversationsAdapter(this, conversations_list) {
|
|
||||||
Intent(this, ThreadActivity::class.java).apply {
|
|
||||||
val conversation = it as Conversation
|
|
||||||
putExtra(THREAD_ID, conversation.threadId)
|
|
||||||
putExtra(THREAD_TITLE, conversation.title)
|
|
||||||
startActivity(this)
|
|
||||||
}
|
|
||||||
}.apply {
|
|
||||||
conversations_list.adapter = this
|
|
||||||
updateConversations(sortedConversations)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (areSystemAnimationsEnabled) {
|
|
||||||
conversations_list.scheduleLayoutAnimation()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
try {
|
||||||
(currAdapter as ConversationsAdapter).updateConversations(sortedConversations) {
|
getOrCreateConversationsAdapter().apply {
|
||||||
if (currAdapter.currentList.isEmpty()) {
|
updateConversations(sortedConversations) {
|
||||||
|
if (currentList.isEmpty()) {
|
||||||
conversations_fastscroller.beGone()
|
conversations_fastscroller.beGone()
|
||||||
no_conversations_placeholder.text = getString(R.string.no_conversations_found)
|
no_conversations_placeholder.text = getString(R.string.no_conversations_found)
|
||||||
no_conversations_placeholder.beVisible()
|
no_conversations_placeholder.beVisible()
|
||||||
no_conversations_placeholder_2.beVisible()
|
no_conversations_placeholder_2.beVisible()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private fun notifyDatasetChanged() {
|
||||||
|
getOrCreateConversationsAdapter().notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleConversationClick(any: Any) {
|
||||||
|
Intent(this, ThreadActivity::class.java).apply {
|
||||||
|
val conversation = any as Conversation
|
||||||
|
putExtra(THREAD_ID, conversation.threadId)
|
||||||
|
putExtra(THREAD_TITLE, conversation.title)
|
||||||
|
startActivity(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun launchNewConversation() {
|
private fun launchNewConversation() {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.simplemobiletools.smsmessenger.adapters
|
package com.simplemobiletools.smsmessenger.adapters
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
@ -31,8 +32,9 @@ import com.simplemobiletools.smsmessenger.models.Conversation
|
|||||||
import kotlinx.android.synthetic.main.item_conversation.view.*
|
import kotlinx.android.synthetic.main.item_conversation.view.*
|
||||||
|
|
||||||
class ConversationsAdapter(
|
class ConversationsAdapter(
|
||||||
activity: SimpleActivity, recyclerView: MyRecyclerView, itemClick: (Any) -> Unit
|
activity: SimpleActivity, recyclerView: MyRecyclerView, onRefresh: () -> Unit, itemClick: (Any) -> Unit
|
||||||
) : MyRecyclerViewListAdapter<Conversation>(activity, recyclerView, ConversationDiffCallback(), itemClick), RecyclerViewFastScroller.OnPopupTextUpdate {
|
) : MyRecyclerViewListAdapter<Conversation>(activity, recyclerView, ConversationDiffCallback(), itemClick, onRefresh),
|
||||||
|
RecyclerViewFastScroller.OnPopupTextUpdate {
|
||||||
private var fontSize = activity.getTextSize()
|
private var fontSize = activity.getTextSize()
|
||||||
private var drafts = HashMap<Long, String?>()
|
private var drafts = HashMap<Long, String?>()
|
||||||
|
|
||||||
@ -40,7 +42,9 @@ class ConversationsAdapter(
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
setupDragListener(true)
|
setupDragListener(true)
|
||||||
|
ensureBackgroundThread {
|
||||||
fetchDrafts(drafts)
|
fetchDrafts(drafts)
|
||||||
|
}
|
||||||
setHasStableIds(true)
|
setHasStableIds(true)
|
||||||
|
|
||||||
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||||
@ -314,13 +318,17 @@ class ConversationsAdapter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updateDrafts() {
|
fun updateDrafts() {
|
||||||
|
ensureBackgroundThread {
|
||||||
val newDrafts = HashMap<Long, String?>()
|
val newDrafts = HashMap<Long, String?>()
|
||||||
fetchDrafts(newDrafts)
|
fetchDrafts(newDrafts)
|
||||||
if (drafts.hashCode() != newDrafts.hashCode()) {
|
if (drafts.hashCode() != newDrafts.hashCode()) {
|
||||||
drafts = newDrafts
|
drafts = newDrafts
|
||||||
|
activity.runOnUiThread {
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupView(view: View, conversation: Conversation) {
|
private fun setupView(view: View, conversation: Conversation) {
|
||||||
view.apply {
|
view.apply {
|
||||||
|
@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
@ -18,7 +19,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
|||||||
import com.bumptech.glide.load.engine.GlideException
|
import com.bumptech.glide.load.engine.GlideException
|
||||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
||||||
import com.bumptech.glide.load.resource.bitmap.FitCenter
|
import com.bumptech.glide.load.resource.bitmap.FitCenter
|
||||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
|
|
||||||
import com.bumptech.glide.request.RequestListener
|
import com.bumptech.glide.request.RequestListener
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
@ -291,7 +291,20 @@ class ThreadAdapter(
|
|||||||
thread_message_body.setLinkTextColor(context.getProperPrimaryColor())
|
thread_message_body.setLinkTextColor(context.getProperPrimaryColor())
|
||||||
|
|
||||||
if (!activity.isFinishing && !activity.isDestroyed) {
|
if (!activity.isFinishing && !activity.isDestroyed) {
|
||||||
SimpleContactsHelper(context).loadContactImage(message.senderPhotoUri, thread_message_sender_photo, message.senderName)
|
val contactLetterIcon = SimpleContactsHelper(context).getContactLetterIcon(message.senderName)
|
||||||
|
val placeholder = BitmapDrawable(context.resources, contactLetterIcon)
|
||||||
|
|
||||||
|
val options = RequestOptions()
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||||
|
.error(placeholder)
|
||||||
|
.centerCrop()
|
||||||
|
|
||||||
|
Glide.with(context)
|
||||||
|
.load(message.senderPhotoUri)
|
||||||
|
.placeholder(placeholder)
|
||||||
|
.apply(options)
|
||||||
|
.apply(RequestOptions.circleCropTransform())
|
||||||
|
.into(thread_message_sender_photo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,7 +354,6 @@ class ThreadAdapter(
|
|||||||
|
|
||||||
var builder = Glide.with(context)
|
var builder = Glide.with(context)
|
||||||
.load(uri)
|
.load(uri)
|
||||||
.transition(DrawableTransitionOptions.withCrossFade())
|
|
||||||
.apply(options)
|
.apply(options)
|
||||||
.listener(object : RequestListener<Drawable> {
|
.listener(object : RequestListener<Drawable> {
|
||||||
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
|
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
|
||||||
|
@ -1,22 +1,13 @@
|
|||||||
package com.simplemobiletools.smsmessenger.extensions
|
package com.simplemobiletools.smsmessenger.extensions
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Notification
|
|
||||||
import android.app.NotificationChannel
|
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.content.ContentValues
|
import android.content.ContentValues
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.media.AudioAttributes
|
|
||||||
import android.media.AudioManager
|
|
||||||
import android.media.RingtoneManager
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.provider.ContactsContract.PhoneLookup
|
import android.provider.ContactsContract.PhoneLookup
|
||||||
@ -24,15 +15,15 @@ import android.provider.OpenableColumns
|
|||||||
import android.provider.Telephony.*
|
import android.provider.Telephony.*
|
||||||
import android.telephony.SubscriptionManager
|
import android.telephony.SubscriptionManager
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.core.app.NotificationCompat
|
import com.bumptech.glide.Glide
|
||||||
import androidx.core.app.RemoteInput
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.klinker.android.send_message.Transaction.getAddressSeparator
|
import com.klinker.android.send_message.Transaction.getAddressSeparator
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.*
|
import com.simplemobiletools.commons.helpers.*
|
||||||
import com.simplemobiletools.commons.models.PhoneNumber
|
import com.simplemobiletools.commons.models.PhoneNumber
|
||||||
import com.simplemobiletools.commons.models.SimpleContact
|
import com.simplemobiletools.commons.models.SimpleContact
|
||||||
import com.simplemobiletools.smsmessenger.R
|
import com.simplemobiletools.smsmessenger.R
|
||||||
import com.simplemobiletools.smsmessenger.activities.ThreadActivity
|
|
||||||
import com.simplemobiletools.smsmessenger.databases.MessagesDatabase
|
import com.simplemobiletools.smsmessenger.databases.MessagesDatabase
|
||||||
import com.simplemobiletools.smsmessenger.helpers.*
|
import com.simplemobiletools.smsmessenger.helpers.*
|
||||||
import com.simplemobiletools.smsmessenger.helpers.AttachmentUtils.parseAttachmentNames
|
import com.simplemobiletools.smsmessenger.helpers.AttachmentUtils.parseAttachmentNames
|
||||||
@ -41,8 +32,6 @@ import com.simplemobiletools.smsmessenger.interfaces.ConversationsDao
|
|||||||
import com.simplemobiletools.smsmessenger.interfaces.MessageAttachmentsDao
|
import com.simplemobiletools.smsmessenger.interfaces.MessageAttachmentsDao
|
||||||
import com.simplemobiletools.smsmessenger.interfaces.MessagesDao
|
import com.simplemobiletools.smsmessenger.interfaces.MessagesDao
|
||||||
import com.simplemobiletools.smsmessenger.models.*
|
import com.simplemobiletools.smsmessenger.models.*
|
||||||
import com.simplemobiletools.smsmessenger.receivers.DirectReplyReceiver
|
|
||||||
import com.simplemobiletools.smsmessenger.receivers.MarkAsReadReceiver
|
|
||||||
import me.leolin.shortcutbadger.ShortcutBadger
|
import me.leolin.shortcutbadger.ShortcutBadger
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
|
|
||||||
@ -58,6 +47,8 @@ val Context.messageAttachmentsDB: MessageAttachmentsDao get() = getMessagesDB().
|
|||||||
|
|
||||||
val Context.messagesDB: MessagesDao get() = getMessagesDB().MessagesDao()
|
val Context.messagesDB: MessagesDao get() = getMessagesDB().MessagesDao()
|
||||||
|
|
||||||
|
val Context.notificationHelper get() = NotificationHelper(this)
|
||||||
|
|
||||||
fun Context.getMessages(
|
fun Context.getMessages(
|
||||||
threadId: Long,
|
threadId: Long,
|
||||||
getImageResolutions: Boolean,
|
getImageResolutions: Boolean,
|
||||||
@ -713,12 +704,12 @@ fun Context.getThreadId(addresses: Set<String>): Long {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) {
|
fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) {
|
||||||
val privateCursor = getMyContactsCursor(false, true)
|
val privateCursor = getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val senderName = getNameFromAddress(address, privateCursor)
|
val senderName = getNameFromAddress(address, privateCursor)
|
||||||
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
showMessageNotification(address, body, threadId, bitmap, senderName)
|
notificationHelper.showMessageNotification(address, body, threadId, bitmap, senderName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -746,130 +737,26 @@ fun Context.getContactFromAddress(address: String, callback: ((contact: SimpleCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
fun Context.getNotificationBitmap(photoUri: String): Bitmap? {
|
||||||
fun Context.showMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?, sender: String) {
|
val size = resources.getDimension(R.dimen.notification_large_icon_size).toInt()
|
||||||
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
if (photoUri.isEmpty()) {
|
||||||
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
|
return null
|
||||||
if (isOreoPlus()) {
|
|
||||||
val audioAttributes = AudioAttributes.Builder()
|
|
||||||
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
|
|
||||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
|
||||||
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val name = getString(R.string.channel_received_sms)
|
|
||||||
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(this, ThreadActivity::class.java).apply {
|
val options = RequestOptions()
|
||||||
putExtra(THREAD_ID, threadId)
|
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
||||||
}
|
.centerCrop()
|
||||||
|
|
||||||
val pendingIntent = PendingIntent.getActivity(this, threadId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
|
return try {
|
||||||
val summaryText = getString(R.string.new_message)
|
Glide.with(this)
|
||||||
val markAsReadIntent = Intent(this, MarkAsReadReceiver::class.java).apply {
|
.asBitmap()
|
||||||
action = MARK_AS_READ
|
.load(photoUri)
|
||||||
putExtra(THREAD_ID, threadId)
|
.apply(options)
|
||||||
}
|
.apply(RequestOptions.circleCropTransform())
|
||||||
|
.into(size, size)
|
||||||
val markAsReadPendingIntent =
|
.get()
|
||||||
PendingIntent.getBroadcast(this, threadId.hashCode(), markAsReadIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
|
} catch (e: Exception) {
|
||||||
var replyAction: NotificationCompat.Action? = null
|
null
|
||||||
|
|
||||||
if (isNougatPlus()) {
|
|
||||||
val replyLabel = getString(R.string.reply)
|
|
||||||
val remoteInput = RemoteInput.Builder(REPLY)
|
|
||||||
.setLabel(replyLabel)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val replyIntent = Intent(this, DirectReplyReceiver::class.java).apply {
|
|
||||||
putExtra(THREAD_ID, threadId)
|
|
||||||
putExtra(THREAD_NUMBER, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
val replyPendingIntent =
|
|
||||||
PendingIntent.getBroadcast(applicationContext, threadId.hashCode(), replyIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
|
|
||||||
replyAction = NotificationCompat.Action.Builder(R.drawable.ic_send_vector, replyLabel, replyPendingIntent)
|
|
||||||
.addRemoteInput(remoteInput)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
val largeIcon = bitmap ?: SimpleContactsHelper(this).getContactLetterIcon(sender)
|
|
||||||
val builder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL).apply {
|
|
||||||
when (config.lockScreenVisibilitySetting) {
|
|
||||||
LOCK_SCREEN_SENDER_MESSAGE -> {
|
|
||||||
setLargeIcon(largeIcon)
|
|
||||||
setStyle(getMessagesStyle(notificationManager, threadId, sender, body))
|
|
||||||
}
|
|
||||||
LOCK_SCREEN_SENDER -> {
|
|
||||||
setContentTitle(sender)
|
|
||||||
setLargeIcon(largeIcon)
|
|
||||||
setStyle(NotificationCompat.BigTextStyle().setSummaryText(summaryText).bigText(body))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
color = getProperPrimaryColor()
|
|
||||||
setSmallIcon(R.drawable.ic_messenger)
|
|
||||||
setContentIntent(pendingIntent)
|
|
||||||
priority = NotificationCompat.PRIORITY_MAX
|
|
||||||
setDefaults(Notification.DEFAULT_LIGHTS)
|
|
||||||
setCategory(Notification.CATEGORY_MESSAGE)
|
|
||||||
setAutoCancel(true)
|
|
||||||
setSound(soundUri, AudioManager.STREAM_NOTIFICATION)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (replyAction != null && config.lockScreenVisibilitySetting == LOCK_SCREEN_SENDER_MESSAGE) {
|
|
||||||
builder.addAction(replyAction)
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.addAction(R.drawable.ic_check_vector, getString(R.string.mark_as_read), markAsReadPendingIntent)
|
|
||||||
.setChannelId(NOTIFICATION_CHANNEL)
|
|
||||||
|
|
||||||
notificationManager.notify(threadId.hashCode(), builder.build())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Context.getMessagesStyle(
|
|
||||||
notificationManager: NotificationManager,
|
|
||||||
threadId: Long,
|
|
||||||
sender: String,
|
|
||||||
body: String
|
|
||||||
): NotificationCompat.MessagingStyle {
|
|
||||||
val oldMessages = getOldMessages(notificationManager, threadId)
|
|
||||||
val messages = NotificationCompat.MessagingStyle(getString(R.string.me))
|
|
||||||
oldMessages.forEach {
|
|
||||||
messages.addMessage(it)
|
|
||||||
}
|
|
||||||
val currentMessage = NotificationCompat.MessagingStyle.Message(body, System.currentTimeMillis(), sender)
|
|
||||||
messages.addMessage(currentMessage)
|
|
||||||
return messages
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getOldMessages(notificationManager: NotificationManager, threadId: Long): List<NotificationCompat.MessagingStyle.Message> {
|
|
||||||
if (!isNougatPlus()) {
|
|
||||||
return arrayListOf()
|
|
||||||
}
|
|
||||||
val currentNotification = notificationManager.activeNotifications.find { it.id == threadId.hashCode() }
|
|
||||||
return if (currentNotification != null) {
|
|
||||||
val messages = currentNotification.notification.extras.getParcelableArray(NotificationCompat.EXTRA_MESSAGES)
|
|
||||||
val result = arrayListOf<NotificationCompat.MessagingStyle.Message>()
|
|
||||||
messages?.forEach {
|
|
||||||
val bundle = it as Bundle
|
|
||||||
val sender = bundle.getCharSequence("sender")
|
|
||||||
val text = bundle.getCharSequence("text")
|
|
||||||
val time = bundle.getLong("time")
|
|
||||||
val message = NotificationCompat.MessagingStyle.Message(text, time, sender)
|
|
||||||
result.add(message)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
arrayListOf()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,198 @@
|
|||||||
|
package com.simplemobiletools.smsmessenger.helpers
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Notification
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager.IMPORTANCE_HIGH
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.media.AudioAttributes
|
||||||
|
import android.media.AudioManager
|
||||||
|
import android.media.RingtoneManager
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.app.Person
|
||||||
|
import androidx.core.app.RemoteInput
|
||||||
|
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
|
||||||
|
import com.simplemobiletools.commons.extensions.notificationManager
|
||||||
|
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
||||||
|
import com.simplemobiletools.commons.helpers.isNougatPlus
|
||||||
|
import com.simplemobiletools.commons.helpers.isOreoPlus
|
||||||
|
import com.simplemobiletools.smsmessenger.R
|
||||||
|
import com.simplemobiletools.smsmessenger.activities.ThreadActivity
|
||||||
|
import com.simplemobiletools.smsmessenger.extensions.config
|
||||||
|
import com.simplemobiletools.smsmessenger.receivers.DirectReplyReceiver
|
||||||
|
import com.simplemobiletools.smsmessenger.receivers.MarkAsReadReceiver
|
||||||
|
|
||||||
|
class NotificationHelper(private val context: Context) {
|
||||||
|
|
||||||
|
private val notificationManager = context.notificationManager
|
||||||
|
private val soundUri get() = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
|
||||||
|
private val user = Person.Builder()
|
||||||
|
.setName(context.getString(R.string.me))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
fun showMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?, sender: String?, alertOnlyOnce: Boolean = false) {
|
||||||
|
maybeCreateChannel(name = context.getString(R.string.channel_received_sms))
|
||||||
|
|
||||||
|
val notificationId = threadId.hashCode()
|
||||||
|
val contentIntent = Intent(context, ThreadActivity::class.java).apply {
|
||||||
|
putExtra(THREAD_ID, threadId)
|
||||||
|
}
|
||||||
|
val contentPendingIntent =
|
||||||
|
PendingIntent.getActivity(context, notificationId, contentIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
|
||||||
|
|
||||||
|
val markAsReadIntent = Intent(context, MarkAsReadReceiver::class.java).apply {
|
||||||
|
action = MARK_AS_READ
|
||||||
|
putExtra(THREAD_ID, threadId)
|
||||||
|
}
|
||||||
|
val markAsReadPendingIntent =
|
||||||
|
PendingIntent.getBroadcast(context, notificationId, markAsReadIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
|
||||||
|
|
||||||
|
var replyAction: NotificationCompat.Action? = null
|
||||||
|
if (isNougatPlus()) {
|
||||||
|
val replyLabel = context.getString(R.string.reply)
|
||||||
|
val remoteInput = RemoteInput.Builder(REPLY)
|
||||||
|
.setLabel(replyLabel)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val replyIntent = Intent(context, DirectReplyReceiver::class.java).apply {
|
||||||
|
putExtra(THREAD_ID, threadId)
|
||||||
|
putExtra(THREAD_NUMBER, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
val replyPendingIntent =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context.applicationContext,
|
||||||
|
notificationId,
|
||||||
|
replyIntent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
|
||||||
|
)
|
||||||
|
replyAction = NotificationCompat.Action.Builder(R.drawable.ic_send_vector, replyLabel, replyPendingIntent)
|
||||||
|
.addRemoteInput(remoteInput)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
val largeIcon = bitmap ?: if (sender != null) {
|
||||||
|
SimpleContactsHelper(context).getContactLetterIcon(sender)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL).apply {
|
||||||
|
when (context.config.lockScreenVisibilitySetting) {
|
||||||
|
LOCK_SCREEN_SENDER_MESSAGE -> {
|
||||||
|
setLargeIcon(largeIcon)
|
||||||
|
setStyle(getMessagesStyle(address, body, notificationId, sender))
|
||||||
|
}
|
||||||
|
LOCK_SCREEN_SENDER -> {
|
||||||
|
setContentTitle(sender)
|
||||||
|
setLargeIcon(largeIcon)
|
||||||
|
val summaryText = context.getString(R.string.new_message)
|
||||||
|
setStyle(NotificationCompat.BigTextStyle().setSummaryText(summaryText).bigText(body))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
color = context.getProperPrimaryColor()
|
||||||
|
setSmallIcon(R.drawable.ic_messenger)
|
||||||
|
setContentIntent(contentPendingIntent)
|
||||||
|
priority = NotificationCompat.PRIORITY_MAX
|
||||||
|
setDefaults(Notification.DEFAULT_LIGHTS)
|
||||||
|
setCategory(Notification.CATEGORY_MESSAGE)
|
||||||
|
setAutoCancel(true)
|
||||||
|
setOnlyAlertOnce(alertOnlyOnce)
|
||||||
|
setSound(soundUri, AudioManager.STREAM_NOTIFICATION)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replyAction != null && context.config.lockScreenVisibilitySetting == LOCK_SCREEN_SENDER_MESSAGE) {
|
||||||
|
builder.addAction(replyAction)
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.addAction(R.drawable.ic_check_vector, context.getString(R.string.mark_as_read), markAsReadPendingIntent)
|
||||||
|
.setChannelId(NOTIFICATION_CHANNEL)
|
||||||
|
|
||||||
|
notificationManager.notify(notificationId, builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
fun showSendingFailedNotification(recipientName: String, threadId: Long) {
|
||||||
|
maybeCreateChannel(name = context.getString(R.string.message_not_sent_short))
|
||||||
|
|
||||||
|
val notificationId = generateRandomId().hashCode()
|
||||||
|
val intent = Intent(context, ThreadActivity::class.java).apply {
|
||||||
|
putExtra(THREAD_ID, threadId)
|
||||||
|
}
|
||||||
|
val contentPendingIntent = PendingIntent.getActivity(context, notificationId, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
|
||||||
|
|
||||||
|
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.getProperPrimaryColor())
|
||||||
|
.setSmallIcon(R.drawable.ic_messenger)
|
||||||
|
.setLargeIcon(largeIcon)
|
||||||
|
.setStyle(NotificationCompat.BigTextStyle().bigText(summaryText))
|
||||||
|
.setContentIntent(contentPendingIntent)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
|
.setDefaults(Notification.DEFAULT_LIGHTS)
|
||||||
|
.setCategory(Notification.CATEGORY_MESSAGE)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setChannelId(NOTIFICATION_CHANNEL)
|
||||||
|
|
||||||
|
notificationManager.notify(notificationId, builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maybeCreateChannel(name: String) {
|
||||||
|
if (isOreoPlus()) {
|
||||||
|
val audioAttributes = AudioAttributes.Builder()
|
||||||
|
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
|
||||||
|
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||||
|
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val id = NOTIFICATION_CHANNEL
|
||||||
|
val importance = IMPORTANCE_HIGH
|
||||||
|
NotificationChannel(id, name, importance).apply {
|
||||||
|
setBypassDnd(false)
|
||||||
|
enableLights(true)
|
||||||
|
setSound(soundUri, audioAttributes)
|
||||||
|
enableVibration(true)
|
||||||
|
notificationManager.createNotificationChannel(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMessagesStyle(address: String, body: String, notificationId: Int, name: String?): NotificationCompat.MessagingStyle {
|
||||||
|
val sender = if (name != null) {
|
||||||
|
Person.Builder()
|
||||||
|
.setName(name)
|
||||||
|
.setKey(address)
|
||||||
|
.build()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
return NotificationCompat.MessagingStyle(user).also { style ->
|
||||||
|
getOldMessages(notificationId).forEach {
|
||||||
|
style.addMessage(it)
|
||||||
|
}
|
||||||
|
val newMessage = NotificationCompat.MessagingStyle.Message(body, System.currentTimeMillis(), sender)
|
||||||
|
style.addMessage(newMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getOldMessages(notificationId: Int): List<NotificationCompat.MessagingStyle.Message> {
|
||||||
|
if (!isNougatPlus()) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
val currentNotification = notificationManager.activeNotifications.find { it.id == notificationId }
|
||||||
|
return if (currentNotification != null) {
|
||||||
|
val activeStyle = NotificationCompat.MessagingStyle.extractMessagingStyleFromNotification(currentNotification.notification)
|
||||||
|
activeStyle?.messages.orEmpty()
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,58 +4,58 @@ import android.annotation.SuppressLint
|
|||||||
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 androidx.core.app.RemoteInput
|
import androidx.core.app.RemoteInput
|
||||||
import com.klinker.android.send_message.Transaction
|
|
||||||
import com.simplemobiletools.commons.extensions.notificationManager
|
|
||||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||||
|
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
import com.simplemobiletools.smsmessenger.extensions.*
|
import com.simplemobiletools.smsmessenger.extensions.*
|
||||||
import com.simplemobiletools.smsmessenger.helpers.REPLY
|
import com.simplemobiletools.smsmessenger.helpers.REPLY
|
||||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_NUMBER
|
import com.simplemobiletools.smsmessenger.helpers.THREAD_NUMBER
|
||||||
import com.simplemobiletools.smsmessenger.helpers.getSendMessageSettings
|
import com.simplemobiletools.smsmessenger.helpers.sendMessage
|
||||||
|
|
||||||
class DirectReplyReceiver : BroadcastReceiver() {
|
class DirectReplyReceiver : BroadcastReceiver() {
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val address = intent.getStringExtra(THREAD_NUMBER)
|
val address = intent.getStringExtra(THREAD_NUMBER)
|
||||||
val threadId = intent.getLongExtra(THREAD_ID, 0L)
|
val threadId = intent.getLongExtra(THREAD_ID, 0L)
|
||||||
var msg = RemoteInput.getResultsFromIntent(intent)?.getCharSequence(REPLY)?.toString() ?: return
|
var body = RemoteInput.getResultsFromIntent(intent)?.getCharSequence(REPLY)?.toString() ?: return
|
||||||
|
|
||||||
msg = context.removeDiacriticsIfNeeded(msg)
|
body = context.removeDiacriticsIfNeeded(body)
|
||||||
|
|
||||||
val settings = context.getSendMessageSettings()
|
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
|
var subscriptionId: Int? = null
|
||||||
val availableSIMs = context.subscriptionManagerCompat().activeSubscriptionInfoList
|
val availableSIMs = context.subscriptionManagerCompat().activeSubscriptionInfoList
|
||||||
if ((availableSIMs?.size ?: 0) > 1) {
|
if ((availableSIMs?.size ?: 0) > 1) {
|
||||||
val currentSIMCardIndex = context.config.getUseSIMIdAtNumber(address)
|
val currentSIMCardIndex = context.config.getUseSIMIdAtNumber(address)
|
||||||
val wantedId = availableSIMs.getOrNull(currentSIMCardIndex)
|
val wantedId = availableSIMs.getOrNull(currentSIMCardIndex)
|
||||||
if (wantedId != null) {
|
if (wantedId != null) {
|
||||||
settings.subscriptionId = wantedId.subscriptionId
|
subscriptionId = wantedId.subscriptionId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val transaction = Transaction(context, settings)
|
|
||||||
val message = com.klinker.android.send_message.Message(msg, address)
|
|
||||||
|
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
try {
|
try {
|
||||||
val smsSentIntent = Intent(context, SmsStatusSentReceiver::class.java)
|
context.sendMessage(body, listOf(address), subscriptionId, emptyList())
|
||||||
val deliveredIntent = Intent(context, SmsStatusDeliveredReceiver::class.java)
|
val message = context.getMessages(threadId, getImageResolutions = false, includeScheduledMessages = false, limit = 1).lastOrNull()
|
||||||
|
if (message != null) {
|
||||||
transaction.setExplicitBroadcastForSentSms(smsSentIntent)
|
context.messagesDB.insertOrUpdate(message)
|
||||||
transaction.setExplicitBroadcastForDeliveredSms(deliveredIntent)
|
}
|
||||||
|
|
||||||
transaction.sendNewMessage(message)
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.showErrorToast(e)
|
context.showErrorToast(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
context.notificationManager.cancel(threadId.hashCode())
|
val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address)
|
||||||
|
val bitmap = context.getNotificationBitmap(photoUri)
|
||||||
|
Handler(Looper.getMainLooper()).post {
|
||||||
|
context.notificationHelper.showMessageNotification(address, body, threadId, bitmap, sender = null, alertOnlyOnce = true)
|
||||||
|
}
|
||||||
|
|
||||||
context.markThreadMessagesRead(threadId)
|
context.markThreadMessagesRead(threadId)
|
||||||
context.conversationsDB.markRead(threadId)
|
context.conversationsDB.markRead(threadId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,9 @@ package com.simplemobiletools.smsmessenger.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.graphics.Bitmap
|
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.provider.Telephony
|
import android.provider.Telephony
|
||||||
import com.bumptech.glide.Glide
|
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
|
||||||
import com.bumptech.glide.request.RequestOptions
|
|
||||||
import com.simplemobiletools.commons.extensions.baseConfig
|
import com.simplemobiletools.commons.extensions.baseConfig
|
||||||
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
||||||
import com.simplemobiletools.commons.extensions.isNumberBlocked
|
import com.simplemobiletools.commons.extensions.isNumberBlocked
|
||||||
@ -17,7 +13,6 @@ import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
|||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
import com.simplemobiletools.commons.models.PhoneNumber
|
import com.simplemobiletools.commons.models.PhoneNumber
|
||||||
import com.simplemobiletools.commons.models.SimpleContact
|
import com.simplemobiletools.commons.models.SimpleContact
|
||||||
import com.simplemobiletools.smsmessenger.R
|
|
||||||
import com.simplemobiletools.smsmessenger.extensions.*
|
import com.simplemobiletools.smsmessenger.extensions.*
|
||||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||||
import com.simplemobiletools.smsmessenger.models.Message
|
import com.simplemobiletools.smsmessenger.models.Message
|
||||||
@ -63,7 +58,7 @@ class SmsReceiver : BroadcastReceiver() {
|
|||||||
context: Context, address: String, subject: String, body: String, date: Long, read: Int, threadId: Long, type: Int, subscriptionId: Int, status: Int
|
context: Context, address: String, subject: String, body: String, date: Long, read: Int, threadId: Long, type: Int, subscriptionId: Int, status: Int
|
||||||
) {
|
) {
|
||||||
val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address)
|
val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address)
|
||||||
val bitmap = getPhotoForNotification(photoUri, context)
|
val bitmap = context.getNotificationBitmap(photoUri)
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
if (!context.isNumberBlocked(address)) {
|
if (!context.isNumberBlocked(address)) {
|
||||||
val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
|
val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
|
||||||
@ -97,27 +92,4 @@ class SmsReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPhotoForNotification(photoUri: String, context: Context): Bitmap? {
|
|
||||||
val size = context.resources.getDimension(R.dimen.notification_large_icon_size).toInt()
|
|
||||||
if (photoUri.isEmpty()) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val options = RequestOptions()
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
|
|
||||||
.centerCrop()
|
|
||||||
|
|
||||||
return try {
|
|
||||||
Glide.with(context)
|
|
||||||
.asBitmap()
|
|
||||||
.load(photoUri)
|
|
||||||
.apply(options)
|
|
||||||
.apply(RequestOptions.circleCropTransform())
|
|
||||||
.into(size, size)
|
|
||||||
.get()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,18 @@
|
|||||||
package com.simplemobiletools.smsmessenger.receivers
|
package com.simplemobiletools.smsmessenger.receivers
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.app.Activity
|
||||||
import android.app.Notification
|
|
||||||
import android.app.NotificationChannel
|
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.media.AudioAttributes
|
|
||||||
import android.media.AudioManager
|
|
||||||
import android.media.RingtoneManager
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.provider.Telephony
|
import android.provider.Telephony
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
import com.klinker.android.send_message.SentReceiver
|
import com.klinker.android.send_message.SentReceiver
|
||||||
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
import com.simplemobiletools.commons.extensions.getMyContactsCursor
|
||||||
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
|
|
||||||
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
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.extensions.*
|
||||||
import com.simplemobiletools.smsmessenger.helpers.NOTIFICATION_CHANNEL
|
|
||||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
|
||||||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||||
|
|
||||||
class SmsStatusSentReceiver : SentReceiver() {
|
class SmsStatusSentReceiver : SentReceiver() {
|
||||||
@ -35,11 +22,11 @@ class SmsStatusSentReceiver : SentReceiver() {
|
|||||||
val uri = Uri.parse(intent.getStringExtra("message_uri"))
|
val uri = Uri.parse(intent.getStringExtra("message_uri"))
|
||||||
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
|
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val type = if (intent.extras!!.containsKey("errorCode")) {
|
val type = if (receiverResultCode == Activity.RESULT_OK) {
|
||||||
|
Telephony.Sms.MESSAGE_TYPE_SENT
|
||||||
|
} else {
|
||||||
showSendingFailedNotification(context, messageId)
|
showSendingFailedNotification(context, messageId)
|
||||||
Telephony.Sms.MESSAGE_TYPE_FAILED
|
Telephony.Sms.MESSAGE_TYPE_FAILED
|
||||||
} else {
|
|
||||||
Telephony.Sms.MESSAGE_TYPE_SENT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context.updateMessageType(messageId, type)
|
context.updateMessageType(messageId, type)
|
||||||
@ -59,61 +46,16 @@ class SmsStatusSentReceiver : SentReceiver() {
|
|||||||
|
|
||||||
private fun showSendingFailedNotification(context: Context, messageId: Long) {
|
private fun showSendingFailedNotification(context: Context, messageId: Long) {
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
val privateCursor = context.getMyContactsCursor(false, true)
|
if (ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
||||||
|
return@post
|
||||||
|
}
|
||||||
|
val privateCursor = context.getMyContactsCursor(favoritesOnly = false, withPhoneNumbersOnly = true)
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val address = context.getMessageRecipientAddress(messageId)
|
val address = context.getMessageRecipientAddress(messageId)
|
||||||
val threadId = context.getThreadId(address)
|
val threadId = context.getThreadId(address)
|
||||||
val senderName = context.getNameFromAddress(address, privateCursor)
|
val recipientName = context.getNameFromAddress(address, privateCursor)
|
||||||
showNotification(context, senderName, threadId)
|
context.notificationHelper.showSendingFailedNotification(recipientName, 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 or PendingIntent.FLAG_MUTABLE)
|
|
||||||
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.getProperPrimaryColor())
|
|
||||||
.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())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user