Show basic notification when push is recieve
This commit is contained in:
parent
1f09f5f0eb
commit
afbd4672e6
10 changed files with 124 additions and 16 deletions
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.x.intent
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
|
import io.element.android.libraries.push.impl.intent.IntentProvider
|
||||||
|
import io.element.android.x.MainActivity
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
// TODO EAx change to deep-link.
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class IntentProviderImpl @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
|
) : IntentProvider {
|
||||||
|
override fun getMainIntent(): Intent {
|
||||||
|
return Intent(context, MainActivity::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -67,7 +67,7 @@ class PushersManager @Inject constructor(
|
||||||
val client = matrixAuthenticationService.restoreSession(SessionId(sessionData.userId)).getOrNull()
|
val client = matrixAuthenticationService.restoreSession(SessionId(sessionData.userId)).getOrNull()
|
||||||
client ?: return@forEach
|
client ?: return@forEach
|
||||||
client.pushersService().setHttpPusher(createHttpPusher(pushKey, gateway, sessionData.userId))
|
client.pushersService().setHttpPusher(createHttpPusher(pushKey, gateway, sessionData.userId))
|
||||||
// Close sessions?
|
// TODO EAx Close sessions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ class PushersManager @Inject constructor(
|
||||||
// Register the pusher for the session
|
// Register the pusher for the session
|
||||||
val client = matrixAuthenticationService.restoreSession(userId).getOrNull() ?: return
|
val client = matrixAuthenticationService.restoreSession(userId).getOrNull() ?: return
|
||||||
client.pushersService().setHttpPusher(createHttpPusher(pushKey, PushConfig.pusher_http_url, userId.value))
|
client.pushersService().setHttpPusher(createHttpPusher(pushKey, PushConfig.pusher_http_url, userId.value))
|
||||||
// Close sessions?
|
// TODO EAx Close sessions
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun createHttpPusher(
|
private suspend fun createHttpPusher(
|
||||||
|
|
|
||||||
|
|
@ -142,9 +142,12 @@ class VectorPushHandler @Inject constructor(
|
||||||
eventId = pushData.eventId,
|
eventId = pushData.eventId,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO Remove
|
||||||
Timber.w("Notification: $notificationData")
|
Timber.w("Notification: $notificationData")
|
||||||
// TODO Display notification
|
// TODO Display notification
|
||||||
|
|
||||||
|
notificationDrawerManager.displayTemporaryNotification()
|
||||||
|
|
||||||
/* TODO EAx
|
/* TODO EAx
|
||||||
- get the event
|
- get the event
|
||||||
- display the notif
|
- display the notif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.push.impl.intent
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
|
||||||
|
interface IntentProvider {
|
||||||
|
/**
|
||||||
|
* Provide an intent to start the application
|
||||||
|
*/
|
||||||
|
fun getMainIntent(): Intent
|
||||||
|
}
|
||||||
|
|
@ -16,20 +16,28 @@
|
||||||
|
|
||||||
package io.element.android.libraries.push.impl.notifications
|
package io.element.android.libraries.push.impl.notifications
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class NotificationDisplayer @Inject constructor(
|
const val TEMPORARY_ID = 101
|
||||||
@ApplicationContext context: Context,
|
|
||||||
) {
|
|
||||||
|
|
||||||
|
class NotificationDisplayer @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
|
) {
|
||||||
private val notificationManager = NotificationManagerCompat.from(context)
|
private val notificationManager = NotificationManagerCompat.from(context)
|
||||||
|
|
||||||
fun showNotificationMessage(tag: String?, id: Int, notification: Notification) {
|
fun showNotificationMessage(tag: String?, id: Int, notification: Notification) {
|
||||||
|
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Timber.w("Not allowed to notify.")
|
||||||
|
return
|
||||||
|
}
|
||||||
notificationManager.notify(tag, id, notification)
|
notificationManager.notify(tag, id, notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ import javax.inject.Inject
|
||||||
@SingleIn(AppScope::class)
|
@SingleIn(AppScope::class)
|
||||||
class NotificationDrawerManager @Inject constructor(
|
class NotificationDrawerManager @Inject constructor(
|
||||||
@ApplicationContext context: Context,
|
@ApplicationContext context: Context,
|
||||||
private val notificationDisplayer: NotificationDisplayer,
|
|
||||||
private val pushDataStore: PushDataStore,
|
private val pushDataStore: PushDataStore,
|
||||||
// private val activeSessionDataSource: ActiveSessionDataSource,
|
// private val activeSessionDataSource: ActiveSessionDataSource,
|
||||||
private val notifiableEventProcessor: NotifiableEventProcessor,
|
private val notifiableEventProcessor: NotifiableEventProcessor,
|
||||||
|
|
@ -154,7 +153,7 @@ class NotificationDrawerManager @Inject constructor(
|
||||||
val newSettings = pushDataStore.useCompleteNotificationFormat()
|
val newSettings = pushDataStore.useCompleteNotificationFormat()
|
||||||
if (newSettings != useCompleteNotificationFormat) {
|
if (newSettings != useCompleteNotificationFormat) {
|
||||||
// Settings has changed, remove all current notifications
|
// Settings has changed, remove all current notifications
|
||||||
notificationDisplayer.cancelAllNotifications()
|
notificationRenderer.cancelAllNotifications()
|
||||||
useCompleteNotificationFormat = newSettings
|
useCompleteNotificationFormat = newSettings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -232,6 +231,13 @@ class NotificationDrawerManager @Inject constructor(
|
||||||
return resolvedEvent.shouldIgnoreMessageEventInRoom(currentRoomId, currentThreadId)
|
return resolvedEvent.shouldIgnoreMessageEventInRoom(currentRoomId, currentThreadId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary notification for EAx
|
||||||
|
*/
|
||||||
|
fun displayTemporaryNotification() {
|
||||||
|
notificationRenderer.displayTemporaryNotification()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val SUMMARY_NOTIFICATION_ID = 0
|
const val SUMMARY_NOTIFICATION_ID = 0
|
||||||
const val ROOM_MESSAGES_NOTIFICATION_ID = 1
|
const val ROOM_MESSAGES_NOTIFICATION_ID = 1
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,10 @@ class NotificationFactory @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createTemporaryNotification(): Notification {
|
||||||
|
return notificationUtils.createTemporaryNotification()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface RoomNotification {
|
sealed interface RoomNotification {
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,15 @@ class NotificationRenderer @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun cancelAllNotifications() {
|
||||||
|
notificationDisplayer.cancelAllNotifications()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun displayTemporaryNotification() {
|
||||||
|
val notification = notificationFactory.createTemporaryNotification()
|
||||||
|
notificationDisplayer.showNotificationMessage(null, TEMPORARY_ID, notification)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<ProcessedEvent<NotifiableEvent>>.groupByType(): GroupedNotificationEvents {
|
private fun List<ProcessedEvent<NotifiableEvent>>.groupByType(): GroupedNotificationEvents {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.di.ApplicationContext
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
import io.element.android.libraries.di.SingleIn
|
import io.element.android.libraries.di.SingleIn
|
||||||
import io.element.android.libraries.push.impl.R
|
import io.element.android.libraries.push.impl.R
|
||||||
|
import io.element.android.libraries.push.impl.intent.IntentProvider
|
||||||
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
|
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
|
||||||
import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent
|
import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent
|
||||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
|
|
@ -61,6 +62,7 @@ class NotificationUtils @Inject constructor(
|
||||||
private val stringProvider: StringProvider,
|
private val stringProvider: StringProvider,
|
||||||
private val clock: SystemClock,
|
private val clock: SystemClock,
|
||||||
private val actionIds: NotificationActionIds,
|
private val actionIds: NotificationActionIds,
|
||||||
|
private val intentProvider: IntentProvider,
|
||||||
private val buildMeta: BuildMeta,
|
private val buildMeta: BuildMeta,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
@ -107,6 +109,10 @@ class NotificationUtils @Inject constructor(
|
||||||
|
|
||||||
private val notificationManager = NotificationManagerCompat.from(context)
|
private val notificationManager = NotificationManagerCompat.from(context)
|
||||||
|
|
||||||
|
init {
|
||||||
|
createNotificationChannels()
|
||||||
|
}
|
||||||
|
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
* Channel names
|
* Channel names
|
||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
|
|
@ -114,7 +120,7 @@ class NotificationUtils @Inject constructor(
|
||||||
/**
|
/**
|
||||||
* Create notification channels.
|
* Create notification channels.
|
||||||
*/
|
*/
|
||||||
fun createNotificationChannels() {
|
private fun createNotificationChannels() {
|
||||||
if (!supportNotificationChannels()) {
|
if (!supportNotificationChannels()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -650,14 +656,6 @@ class NotificationUtils @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showNotificationMessage(tag: String?, id: Int, notification: Notification) {
|
|
||||||
notificationManager.notify(tag, id, notification)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cancelNotificationMessage(tag: String?, id: Int) {
|
|
||||||
notificationManager.cancel(tag, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel the foreground notification service.
|
* Cancel the foreground notification service.
|
||||||
*/
|
*/
|
||||||
|
|
@ -705,6 +703,23 @@ class NotificationUtils @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createTemporaryNotification(): Notification {
|
||||||
|
val contentIntent = intentProvider.getMainIntent()
|
||||||
|
val pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, PendingIntentCompat.FLAG_IMMUTABLE)
|
||||||
|
|
||||||
|
return NotificationCompat.Builder(context, NOISY_NOTIFICATION_CHANNEL_ID)
|
||||||
|
.setContentTitle(buildMeta.applicationName)
|
||||||
|
.setContentText(stringProvider.getString(R.string.notification_new_messages_temporary))
|
||||||
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
|
.setLargeIcon(getBitmap(context, R.drawable.element_logo_green))
|
||||||
|
.setColor(ContextCompat.getColor(context, R.color.notification_accent_color))
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
|
.setCategory(NotificationCompat.CATEGORY_STATUS)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
private fun getBitmap(context: Context, @DrawableRes drawableRes: Int): Bitmap? {
|
private fun getBitmap(context: Context, @DrawableRes drawableRes: Int): Bitmap? {
|
||||||
val drawable = ResourcesCompat.getDrawable(context.resources, drawableRes, null) ?: return null
|
val drawable = ResourcesCompat.getDrawable(context.resources, drawableRes, null) ?: return null
|
||||||
val canvas = Canvas()
|
val canvas = Canvas()
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
<string name="notification_silent_notifications">Silent notifications</string>
|
<string name="notification_silent_notifications">Silent notifications</string>
|
||||||
<string name="call">Call</string>
|
<string name="call">Call</string>
|
||||||
<string name="notification_new_messages">New Messages</string>
|
<string name="notification_new_messages">New Messages</string>
|
||||||
|
<string name="notification_new_messages_temporary">You have new message(s)</string>
|
||||||
<string name="action_mark_room_read">Mark as read</string>
|
<string name="action_mark_room_read">Mark as read</string>
|
||||||
<string name="action_join">Join</string>
|
<string name="action_join">Join</string>
|
||||||
<string name="action_reject">Reject</string>
|
<string name="action_reject">Reject</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue