Added custom notifications

This commit is contained in:
Agnieszka C 2023-12-22 09:18:47 +01:00
parent 3455a92e66
commit 535d722936
8 changed files with 154 additions and 10 deletions

View file

@ -1,10 +1,21 @@
package org.fossify.smsmessenger.activities
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.RingtoneManager
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import androidx.annotation.RequiresApi
import androidx.core.content.res.ResourcesCompat
import org.fossify.commons.extensions.*
import org.fossify.commons.helpers.NavigationIcon
import org.fossify.commons.helpers.ensureBackgroundThread
import org.fossify.commons.helpers.isOreoPlus
import org.fossify.commons.models.SimpleContact
import org.fossify.smsmessenger.adapters.ContactsAdapter
import org.fossify.smsmessenger.databinding.ActivityConversationDetailsBinding
@ -46,6 +57,9 @@ class ConversationDetailsActivity : SimpleActivity() {
runOnUiThread {
setupTextViews()
setupParticipants()
if (isOreoPlus()) {
setupCustomNotifications()
}
}
}
}
@ -60,6 +74,62 @@ class ConversationDetailsActivity : SimpleActivity() {
binding.membersHeading.setTextColor(primaryColor)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun setupCustomNotifications() {
binding.apply {
notificationsHeading.beVisible()
customNotificationsHolder.beVisible()
customNotifications.isChecked = config.customNotifications.contains(threadId.toString())
customNotificationsButton.beVisibleIf(customNotifications.isChecked)
customNotificationsHolder.setOnClickListener {
customNotifications.toggle()
if (customNotifications.isChecked) {
customNotificationsButton.beVisible()
config.addCustomNotificationsByThreadId(threadId)
createNotificationChannel()
} else {
customNotificationsButton.beGone()
config.removeCustomNotificationsByThreadId(threadId)
removeNotificationChannel()
}
}
customNotificationsButton.setOnClickListener {
Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).apply {
putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
putExtra(Settings.EXTRA_CHANNEL_ID, threadId.hashCode().toString())
startActivity(this)
}
}
}
}
private fun getNotificationManager() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel() {
val name = conversation?.title
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
.build()
NotificationChannel(threadId.hashCode().toString(), name, NotificationManager.IMPORTANCE_HIGH).apply {
setBypassDnd(false)
enableLights(true)
setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), audioAttributes)
enableVibration(true)
getNotificationManager().createNotificationChannel(this)
}
}
@RequiresApi(Build.VERSION_CODES.O)
private fun removeNotificationChannel() {
getNotificationManager().deleteNotificationChannel(threadId.hashCode().toString())
}
private fun setupTextViews() {
binding.conversationName.apply {
ResourcesCompat.getDrawable(resources, org.fossify.commons.R.drawable.ic_edit_vector, theme)?.apply {

View file

@ -2,6 +2,7 @@ package org.fossify.smsmessenger.extensions
import android.annotation.SuppressLint
import android.app.Application
import android.app.NotificationManager
import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
@ -690,6 +691,12 @@ fun Context.deleteConversation(threadId: Long) {
conversationsDB.deleteThreadId(threadId)
messagesDB.deleteThreadMessages(threadId)
if (config.customNotifications.contains(threadId.toString()) && isOreoPlus()) {
config.removeCustomNotificationsByThreadId(threadId)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.deleteNotificationChannel(threadId.hashCode().toString())
}
}
fun Context.checkAndDeleteOldRecycleBinMessages(callback: (() -> Unit)? = null) {

View file

@ -115,4 +115,16 @@ class Config(context: Context) : BaseConfig(context) {
var isArchiveAvailable: Boolean
get() = prefs.getBoolean(IS_ARCHIVE_AVAILABLE, true)
set(isArchiveAvailable) = prefs.edit().putBoolean(IS_ARCHIVE_AVAILABLE, isArchiveAvailable).apply()
var customNotifications: Set<String>
get() = prefs.getStringSet(CUSTOM_NOTIFICATIONS, HashSet<String>())!!
set(customNotifications) = prefs.edit().putStringSet(CUSTOM_NOTIFICATIONS, customNotifications).apply()
fun addCustomNotificationsByThreadId(threadId: Long) {
customNotifications = customNotifications.plus(threadId.toString())
}
fun removeCustomNotificationsByThreadId(threadId: Long) {
customNotifications = customNotifications.minus(threadId.toString())
}
}

View file

@ -44,6 +44,7 @@ const val USE_RECYCLE_BIN = "use_recycle_bin"
const val LAST_RECYCLE_BIN_CHECK = "last_recycle_bin_check"
const val IS_RECYCLE_BIN = "is_recycle_bin"
const val IS_ARCHIVE_AVAILABLE = "is_archive_available"
const val CUSTOM_NOTIFICATIONS = "custom_notifications"
private const val PATH = "org.fossify.smsmessenger.action."
const val MARK_AS_READ = PATH + "mark_as_read"

View file

@ -45,9 +45,14 @@ class NotificationHelper(private val context: Context) {
sender: String?,
alertOnlyOnce: Boolean = false
) {
maybeCreateChannel(name = context.getString(R.string.channel_received_sms))
val notificationId = threadId.hashCode()
val hasCustomNotifications = context.config.customNotifications.contains(threadId.toString())
val notificationChannel = if (hasCustomNotifications) notificationId.toString() else NOTIFICATION_CHANNEL
if (!hasCustomNotifications) {
maybeCreateChannel(notificationChannel, context.getString(R.string.channel_received_sms))
}
val contentIntent = Intent(context, ThreadActivity::class.java).apply {
putExtra(THREAD_ID, threadId)
}
@ -98,7 +103,7 @@ class NotificationHelper(private val context: Context) {
} else {
null
}
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL).apply {
val builder = NotificationCompat.Builder(context, notificationChannel).apply {
when (context.config.lockScreenVisibilitySetting) {
LOCK_SCREEN_SENDER_MESSAGE -> {
setLargeIcon(largeIcon)
@ -129,20 +134,24 @@ class NotificationHelper(private val context: Context) {
}
builder.addAction(org.fossify.commons.R.drawable.ic_check_vector, context.getString(R.string.mark_as_read), markAsReadPendingIntent)
.setChannelId(NOTIFICATION_CHANNEL)
.setChannelId(notificationChannel)
if (isNoReplySms) {
builder.addAction(
org.fossify.commons.R.drawable.ic_delete_vector,
context.getString(org.fossify.commons.R.string.delete),
deleteSmsPendingIntent
).setChannelId(NOTIFICATION_CHANNEL)
).setChannelId(notificationChannel)
}
notificationManager.notify(notificationId, builder.build())
}
@SuppressLint("NewApi")
fun showSendingFailedNotification(recipientName: String, threadId: Long) {
maybeCreateChannel(name = context.getString(R.string.message_not_sent_short))
val hasCustomNotifications = context.config.customNotifications.contains(threadId.toString())
val notificationChannel = if (hasCustomNotifications) threadId.hashCode().toString() else NOTIFICATION_CHANNEL
if (!hasCustomNotifications) {
maybeCreateChannel(notificationChannel, context.getString(R.string.message_not_sent_short))
}
val notificationId = generateRandomId().hashCode()
val intent = Intent(context, ThreadActivity::class.java).apply {
@ -152,7 +161,7 @@ class NotificationHelper(private val context: Context) {
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)
val builder = NotificationCompat.Builder(context, notificationChannel)
.setContentTitle(context.getString(R.string.message_not_sent_short))
.setContentText(summaryText)
.setColor(context.getProperPrimaryColor())
@ -164,12 +173,12 @@ class NotificationHelper(private val context: Context) {
.setDefaults(Notification.DEFAULT_LIGHTS)
.setCategory(Notification.CATEGORY_MESSAGE)
.setAutoCancel(true)
.setChannelId(NOTIFICATION_CHANNEL)
.setChannelId(notificationChannel)
notificationManager.notify(notificationId, builder.build())
}
private fun maybeCreateChannel(name: String) {
private fun maybeCreateChannel(id: String, name: String) {
if (isOreoPlus()) {
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
@ -177,7 +186,6 @@ class NotificationHelper(private val context: Context) {
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
.build()
val id = NOTIFICATION_CHANNEL
val importance = IMPORTANCE_HIGH
NotificationChannel(id, name, importance).apply {
setBypassDnd(false)

View file

@ -21,6 +21,50 @@
android:layout_marginTop="?attr/actionBarSize"
android:orientation="vertical">
<TextView
android:id="@+id/notifications_heading"
style="@style/MaterialSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginEnd="@dimen/activity_margin"
android:visibility="gone"
android:text="@string/notifications" />
<RelativeLayout
android:id="@+id/custom_notifications_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<org.fossify.commons.views.MyAppCompatCheckbox
android:id="@+id/custom_notifications"
style="@style/SettingsCheckboxStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/bigger_margin"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginEnd="@dimen/activity_margin"
android:layout_marginBottom="@dimen/bigger_margin"
android:paddingBottom="@dimen/activity_margin"
android:text="@string/use_custom_notifications" />
</RelativeLayout>
<org.fossify.commons.views.MyTextView
android:id="@+id/custom_notifications_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginEnd="@dimen/activity_margin"
android:layout_marginBottom="@dimen/bigger_margin"
android:visibility="gone"
android:text="@string/customize_notifications" />
<include
android:id="@+id/settings_conversation_notifications_divider"
layout="@layout/divider" />
<TextView
android:id="@+id/conversation_name_heading"
style="@style/MaterialSectionLabelStyle"

View file

@ -60,6 +60,7 @@
<string name="mark_as_read">Oznacz jako przeczytane</string>
<string name="mark_as_unread">Oznacz jako nieprzeczytane</string>
<string name="me">Ja</string>
<string name="use_custom_notifications">Używaj niestandardowych powiadomień</string>
<!-- Archive -->
<string name="unarchive">Cofnij archiwizację</string>
<string name="empty_archive">Usuń wszystkie zarchiwizowane rozmowy</string>

View file

@ -58,6 +58,7 @@
<string name="mark_as_read">Mark as Read</string>
<string name="mark_as_unread">Mark as Unread</string>
<string name="me">Me</string>
<string name="use_custom_notifications">Use custom notifications</string>
<!-- Archive -->
<string name="unarchive">Unarchive</string>
<string name="empty_archive">Delete all archived conversations</string>