android: Two more notifications when contact connected or connection request received (#1129)

* Two more notifications when contact connected or connection request received

* Large image in notification

* Do not show contact's icon when it't not permitted

* Sound and vibrate for notification

* No large icon in other cases

* Small change
This commit is contained in:
Stanislav Dmitrenko
2022-09-26 19:28:51 +03:00
committed by GitHub
parent 6c7e81777e
commit 409982ad71
6 changed files with 90 additions and 12 deletions

View File

@@ -103,6 +103,12 @@
android:resource="@xml/file_paths" />
</provider>
<!-- NtfManager action processing (buttons in notifications) -->
<receiver
android:name=".model.NtfManager$NtfActionReceiver"
android:enabled="true"
android:exported="false" />
<!-- SimplexService foreground service -->
<service
android:name=".SimplexService"

View File

@@ -10,8 +10,8 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import chat.simplex.app.*
import chat.simplex.app.views.call.*
import chat.simplex.app.views.helpers.base64ToBitmap
import chat.simplex.app.views.helpers.generalGetString
import chat.simplex.app.views.chatlist.acceptContactRequest
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.usersettings.NotificationPreviewMode
import kotlinx.datetime.Clock
@@ -27,6 +27,8 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
const val LockScreenCallChannel: String = "chat.simplex.app.LOCK_SCREEN_CALL_NOTIFICATION"
const val AcceptCallAction: String = "chat.simplex.app.ACCEPT_CALL"
const val CallNotificationId: Int = -1
private const val ChatIdKey: String = "chatId"
}
private val manager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@@ -39,6 +41,10 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
manager.createNotificationChannel(callNotificationChannel())
}
enum class NotificationAction {
ACCEPT_CONTACT_REQUEST
}
private fun callNotificationChannel(): NotificationChannel {
val callChannel = NotificationChannel(CallChannel, generalGetString(R.string.ntf_channel_calls), NotificationManager.IMPORTANCE_HIGH)
val attrs = AudioAttributes.Builder()
@@ -64,13 +70,31 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
}
}
fun notifyContactRequestReceived(cInfo: ChatInfo.ContactRequest) {
notifyMessageReceived(
chatId = cInfo.id,
displayName = cInfo.displayName,
msgText = generalGetString(R.string.notification_new_contact_request),
image = cInfo.image,
listOf(NotificationAction.ACCEPT_CONTACT_REQUEST)
)
}
fun notifyContactConnected(contact: Contact) {
notifyMessageReceived(
chatId = contact.id,
displayName = contact.displayName,
msgText = generalGetString(R.string.notification_contact_connected)
)
}
fun notifyMessageReceived(cInfo: ChatInfo, cItem: ChatItem) {
if (!cInfo.ntfsEnabled) return
notifyMessageReceived(chatId = cInfo.id, displayName = cInfo.displayName, msgText = hideSecrets(cItem))
}
fun notifyMessageReceived(chatId: String, displayName: String, msgText: String) {
fun notifyMessageReceived(chatId: String, displayName: String, msgText: String, image: String? = null, actions: List<NotificationAction> = emptyList()) {
Log.d(TAG, "notifyMessageReceived $chatId")
val now = Clock.System.now().toEpochMilliseconds()
val recentNotification = (now - prevNtfTime.getOrDefault(chatId, 0) < msgNtfTimeoutMs)
@@ -79,18 +103,36 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
val previewMode = appPreferences.notificationPreviewMode.get()
val title = if (previewMode == NotificationPreviewMode.HIDDEN.name) generalGetString(R.string.notification_preview_somebody) else displayName
val content = if (previewMode != NotificationPreviewMode.MESSAGE.name) generalGetString(R.string.notification_preview_new_message) else msgText
val notification = NotificationCompat.Builder(context, MessageChannel)
val largeIcon = when {
actions.isEmpty() -> null
image == null || previewMode == NotificationPreviewMode.HIDDEN.name -> BitmapFactory.decodeResource(context.resources, R.drawable.icon)
else -> base64ToBitmap(image)
}
val builder = NotificationCompat.Builder(context, MessageChannel)
.setContentTitle(title)
.setContentText(content)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setGroup(MessageGroup)
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN)
.setSmallIcon(R.drawable.ntf_icon)
.setLargeIcon(largeIcon)
.setColor(0x88FFFF)
.setAutoCancel(true)
.setVibrate(if (actions.isEmpty()) null else longArrayOf(0, 250, 250, 250))
.setContentIntent(chatPendingIntent(OpenChatAction, chatId))
.setSilent(recentNotification)
.build()
.setSilent(if (actions.isEmpty()) recentNotification else false)
for (action in actions) {
val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
val actionIntent = Intent(SimplexApp.context, NtfActionReceiver::class.java)
actionIntent.action = action.name
actionIntent.putExtra(ChatIdKey, chatId)
val actionPendingIntent: PendingIntent = PendingIntent.getBroadcast(SimplexApp.context, 0, actionIntent, flags)
val actionButton = when (action) {
NotificationAction.ACCEPT_CONTACT_REQUEST -> generalGetString(R.string.accept)
}
builder.addAction(0, actionButton, actionPendingIntent)
}
val summary = NotificationCompat.Builder(context, MessageChannel)
.setSmallIcon(R.drawable.ntf_icon)
@@ -103,7 +145,7 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
with(NotificationManagerCompat.from(context)) {
// using cInfo.id only shows one notification per chat and updates it when the message arrives
notify(chatId.hashCode(), notification)
notify(chatId.hashCode(), builder.build())
notify(0, summary)
}
}
@@ -141,6 +183,10 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
generalGetString(R.string.notification_preview_somebody)
else
invitation.contact.displayName
val largeIcon = if (image == null || previewMode == NotificationPreviewMode.HIDDEN.name)
BitmapFactory.decodeResource(context.resources, R.drawable.icon)
else
base64ToBitmap(image)
ntfBuilder = ntfBuilder
.setContentTitle(title)
@@ -148,7 +194,7 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setSmallIcon(R.drawable.ntf_icon)
.setLargeIcon(if (image == null) BitmapFactory.decodeResource(context.resources, R.drawable.icon) else base64ToBitmap(image))
.setLargeIcon(largeIcon)
.setColor(0x88FFFF)
.setAutoCancel(true)
with(NotificationManagerCompat.from(context)) {
@@ -183,10 +229,31 @@ class NtfManager(val context: Context, private val appPreferences: AppPreference
var intent = Intent(context, MainActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
.setAction(intentAction)
if (chatId != null) intent = intent.putExtra("chatId", chatId)
if (chatId != null) intent = intent.putExtra(ChatIdKey, chatId)
return TaskStackBuilder.create(context).run {
addNextIntentWithParentStack(intent)
getPendingIntent(uniqueInt, PendingIntent.FLAG_IMMUTABLE)
}
}
/**
* Processes every action specified by [NotificationCompat.Builder.addAction] that comes with [NotificationAction]
* and [ChatInfo.id] as [ChatIdKey] in extra
* */
class NtfActionReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val chatId = intent?.getStringExtra(ChatIdKey) ?: return
val cInfo = SimplexApp.context.chatModel.getChat(chatId)?.chatInfo
when (intent.action) {
NotificationAction.ACCEPT_CONTACT_REQUEST.name -> {
if (cInfo !is ChatInfo.ContactRequest) return
acceptContactRequest(cInfo, SimplexApp.context.chatModel)
SimplexApp.context.chatModel.controller.ntfManager.cancelNotificationsForChat(chatId)
}
else -> {
Log.e(TAG, "Unknown action. Make sure you provide action from NotificationAction enum")
}
}
}
}
}

View File

@@ -6,7 +6,6 @@ import android.app.ActivityManager.RunningAppProcessInfo
import android.app.Application
import android.content.*
import android.net.Uri
import android.os.Build
import android.os.PowerManager
import android.provider.Settings
import android.util.Log
@@ -849,7 +848,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
chatModel.updateContact(r.contact)
chatModel.removeChat(r.contact.activeConn.id)
chatModel.updateNetworkStatus(r.contact.id, Chat.NetworkStatus.Connected())
// NtfManager.shared.notifyContactConnected(contact)
ntfManager.notifyContactConnected(r.contact)
}
is CR.ContactConnecting -> {
chatModel.updateContact(r.contact)
@@ -859,7 +858,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a
val contactRequest = r.contactRequest
val cInfo = ChatInfo.ContactRequest(contactRequest)
chatModel.addChat(Chat(chatInfo = cInfo, chatItems = listOf()))
// NtfManager.shared.notifyContactRequest(contactRequest)
ntfManager.notifyContactRequestReceived(cInfo)
}
is CR.ContactUpdated -> {
val cInfo = ChatInfo.Direct(r.toContact)

View File

@@ -112,6 +112,8 @@
<string name="notification_display_mode_hidden_desc">Kontakt und Nachricht verbergen</string>
<string name="notification_preview_somebody">Kontakt verbergen:</string>
<string name="notification_preview_new_message">neue Nachricht</string>
<string name="notification_new_contact_request">New contact request</string>
<string name="notification_contact_connected">Сonnected</string>
<!-- local authentication notice - SimpleXAPI.kt -->
<string name="la_notice_title_simplex_lock">SimpleX Sperre</string>

View File

@@ -112,6 +112,8 @@
<string name="notification_display_mode_hidden_desc">Скрывать контакт и сообщение</string>
<string name="notification_preview_somebody">Контакт скрыт:</string>
<string name="notification_preview_new_message">новое сообщение</string>
<string name="notification_new_contact_request">Новый запрос на соединение</string>
<string name="notification_contact_connected">Соединен(а)</string>
<!-- local authentication notice - SimpleXAPI.kt -->
<string name="la_notice_title_simplex_lock">Блокировка SimpleX</string>

View File

@@ -112,6 +112,8 @@
<string name="notification_display_mode_hidden_desc">Hide contact and message</string>
<string name="notification_preview_somebody">Contact hidden:</string>
<string name="notification_preview_new_message">new message</string>
<string name="notification_new_contact_request">New contact request</string>
<string name="notification_contact_connected">Connected</string>
<!-- local authentication notice - SimpleXAPI.kt -->
<string name="la_notice_title_simplex_lock">SimpleX Lock</string>