diff --git a/CHANGES.rst b/CHANGES.rst index ce1c51d67d..c6f0bd2995 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -41,7 +41,7 @@ Improvements: - Better wording in notification for video call (#1421) - Improve widget banner (#2129) - Icon for Oreo (#2169) - - Notification reliability and Messaging Style. + - Notification reliability and Messaging Style, with inlined reply (#2823, #1016). - Notification settings re-organization, added bing rule troubleshoot - Kotlin Code Improvement in VectorSettingsPreferencesFragment.kt - Remove redundant !! , Replace it with null safe operators in VectorSettingsPreferencesFragment.kt diff --git a/vector/build.gradle b/vector/build.gradle index ac3692c5cc..da085a756f 100755 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -83,6 +83,7 @@ android { resValue "string", "git_revision_date", "\"${gitRevisionDate()}\"" resValue "string", "git_branch_name", "\"${gitBranchName()}\"" resValue "string", "build_number", rootProject.ext.buildNumberProp + buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" minifyEnabled false } @@ -91,6 +92,7 @@ android { resValue "string", "git_revision_date", "\"${gitRevisionDate()}\"" resValue "string", "git_branch_name", "\"${gitBranchName()}\"" resValue "string", "build_number", rootProject.ext.buildNumberProp + buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false" minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } diff --git a/vector/src/app/java/im/vector/push/fcm/VectorFirebaseMessagingService.kt b/vector/src/app/java/im/vector/push/fcm/VectorFirebaseMessagingService.kt index bbb04c7508..548f79b8c9 100755 --- a/vector/src/app/java/im/vector/push/fcm/VectorFirebaseMessagingService.kt +++ b/vector/src/app/java/im/vector/push/fcm/VectorFirebaseMessagingService.kt @@ -1,4 +1,4 @@ -/** +/* * Copyright 2019 New Vector Ltd * * @@ -27,6 +27,7 @@ import com.google.firebase.messaging.RemoteMessage import com.google.gson.JsonParser import im.vector.BuildConfig import im.vector.Matrix +import im.vector.R import im.vector.VectorApp import im.vector.activity.CommonActivityUtils import im.vector.notifications.NotifiableEventResolver @@ -35,7 +36,6 @@ import im.vector.notifications.SimpleNotifiableEvent import im.vector.push.PushManager import im.vector.services.EventStreamService import org.matrix.androidsdk.MXSession -import org.matrix.androidsdk.data.store.IMXStore import org.matrix.androidsdk.rest.model.Event import org.matrix.androidsdk.rest.model.bingrules.BingRule import org.matrix.androidsdk.util.Log @@ -46,9 +46,9 @@ import org.matrix.androidsdk.util.Log class VectorFirebaseMessagingService : FirebaseMessagingService() { // Tells if the events service running state has been tested - private var mCheckLaunched: Boolean = false + private var mCheckLaunched = false - private val notifiableEventResolver: NotifiableEventResolver by lazy { + private val notifiableEventResolver by lazy { NotifiableEventResolver(this) } @@ -64,18 +64,18 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { */ override fun onMessageReceived(message: RemoteMessage?) { if (message == null || message.data == null) { - Log.e(LOG_TAG, "## onMessageReceivedInternal() : received a null message or message with no data") + Log.e(LOG_TAG, "## onMessageReceived() : received a null message or message with no data") return } - if (BuildConfig.DEBUG) { - Log.i(LOG_TAG, "%%%%%%%% :" + message.data.toString()) - Log.i(LOG_TAG, "%%%%%%%% ## onMessageReceived() from FCM with priority " + message.priority) + if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { + Log.i(LOG_TAG, "## onMessageReceived()" + message.data.toString()) + Log.i(LOG_TAG, "## onMessageReceived() from FCM with priority " + message.priority) } //safe guard val pushManager = Matrix.getInstance(applicationContext).pushManager if (!pushManager.areDeviceNotificationsAllowed()) { - Log.i(LOG_TAG, "## onMessageReceivedInternal() : the notifications are disabled") + Log.i(LOG_TAG, "## onMessageReceived() : the notifications are disabled") return } @@ -107,7 +107,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { */ private fun onMessageReceivedInternal(data: Map, pushManager: PushManager) { try { - if (BuildConfig.DEBUG) { + if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { Log.i(LOG_TAG, "## onMessageReceivedInternal() : $data") } // update the badge counter @@ -129,7 +129,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { } catch (e: Exception) { Log.e(LOG_TAG, "## onMessageReceivedInternal() failed : " + e.message, e) } - } //legacy code @@ -160,7 +159,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { for (session in sessions) { if (session.dataHandler?.store?.isReady == true) { session.dataHandler.store?.getEvent(eventId, roomId)?.let { - Log.e(LOG_TAG, "## onMessageReceivedInternal() : ignore the event " + eventId + Log.e(LOG_TAG, "## isEventAlreadyKnown() : ignore the event " + eventId + " in room " + roomId + " because it is already known") return true } @@ -168,7 +167,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { } } } catch (e: Exception) { - Log.e(LOG_TAG, "## onMessageReceivedInternal() : failed to check if the event was already defined " + e.message, e) + Log.e(LOG_TAG, "## isEventAlreadyKnown() : failed to check if the event was already defined " + e.message, e) } } @@ -178,7 +177,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { private fun handleNotificationWithoutSyncingMode(data: Map, session: MXSession?) { if (session == null) { - Log.e(LOG_TAG, "VectorFirebaseMessagingService: handleNotificationWithoutSyncingMode cannot find session") + Log.e(LOG_TAG, "## handleNotificationWithoutSyncingMode cannot find session") return } val notificationDrawerManager = VectorApp.getInstance().notificationDrawerManager @@ -197,7 +196,7 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { session.myUserId, eventId, true, //It's an issue in this case, all event will bing even if expected to be silent. - title = "New Event", + title = getString(R.string.notification_unknown_new_event), description = "", type = null, timestamp = System.currentTimeMillis(), @@ -214,14 +213,14 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { val event = parseEvent(data) if (event?.roomId == null) { //unsupported event - Log.e(LOG_TAG, "VectorFirebaseMessagingService: Received an event with no room id") + Log.e(LOG_TAG, "Received an event with no room id") return } else { var notifiableEvent = notifiableEventResolver.resolveEvent(event, null, session.fulfillRule(event), session) if (notifiableEvent == null) { - Log.e(LOG_TAG, "VectorFirebaseMessagingService: Unsupported notifiable event ${eventId}") + Log.e(LOG_TAG, "Unsupported notifiable event ${eventId}") } else { @@ -260,19 +259,6 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() { return roomName } -// private fun findSenderDisplayNameNameBestEffort(data: Map, session: MXSession?, store: IMXStore?): String? { -// var roomName: String? = data?.get("room_name") -// val roomId = data?.get("room_id") -// if (null == roomName && null != roomId) { -// // Try to get the room name from our store -// if (store?.isReady == true) { -// val room = store.getRoom(roomId) -// roomName = room?.getRoomDisplayName(this) -// } -// } -// return roomName -// } - /** * Try to create an event from the FCM data * diff --git a/vector/src/main/java/im/vector/activity/VectorHomeActivity.java b/vector/src/main/java/im/vector/activity/VectorHomeActivity.java index 660b10140b..33fd85a40b 100644 --- a/vector/src/main/java/im/vector/activity/VectorHomeActivity.java +++ b/vector/src/main/java/im/vector/activity/VectorHomeActivity.java @@ -162,9 +162,6 @@ public class VectorHomeActivity extends VectorAppCompatActivity implements Searc // jump to a group details sheet public static final String EXTRA_GROUP_ID = "VectorHomeActivity.EXTRA_GROUP_ID"; -// -// // When notification is tapped, to know if notification for messages should be cleared -// public static final String EXTRA_CLEAR_ALL_MESSAGES_NOTIFICATIONS = "VectorHomeActivity.EXTRA_CLEAR_ALL_MESSAGES_NOTIFICATIONS"; // there are two ways to open an external link // 1- EXTRA_UNIVERSAL_LINK_URI : the link is opened as soon there is an event check processed (application is launched when clicking on the URI link) diff --git a/vector/src/main/java/im/vector/activity/VectorRoomActivity.java b/vector/src/main/java/im/vector/activity/VectorRoomActivity.java index 6dd0e49662..f4abfb42ef 100755 --- a/vector/src/main/java/im/vector/activity/VectorRoomActivity.java +++ b/vector/src/main/java/im/vector/activity/VectorRoomActivity.java @@ -710,12 +710,6 @@ public void jumpToBottom() { mDefaultTopic = intent.getStringExtra(EXTRA_DEFAULT_TOPIC); mIsUnreadPreviewMode = intent.getBooleanExtra(EXTRA_IS_UNREAD_PREVIEW_MODE, false); - // the user has tapped on the "View" notification button -// if ((null != intent.getAction()) && (intent.getAction().startsWith(NotificationUtils.TAP_TO_VIEW_ACTION))) { -// // remove any pending notifications -// NotificationUtils.INSTANCE.cancelAllNotifications(this); -// } - if (mIsUnreadPreviewMode) { Log.d(LOG_TAG, "Displaying " + roomId + " in unread preview mode"); } else if (!TextUtils.isEmpty(mEventId) || (null != sRoomPreviewData)) { diff --git a/vector/src/main/java/im/vector/notifications/NotifiableEventResolver.kt b/vector/src/main/java/im/vector/notifications/NotifiableEventResolver.kt index a1214c9a3e..401dfc00ca 100644 --- a/vector/src/main/java/im/vector/notifications/NotifiableEventResolver.kt +++ b/vector/src/main/java/im/vector/notifications/NotifiableEventResolver.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018 New Vector Ltd + * Copyright 2019 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. @@ -19,13 +19,21 @@ import android.content.Context import android.support.v4.app.NotificationCompat import android.util.Log import android.widget.ImageView +import im.vector.R import im.vector.util.RiotEventDisplay import org.matrix.androidsdk.MXSession import org.matrix.androidsdk.data.RoomState import org.matrix.androidsdk.data.store.IMXStore import org.matrix.androidsdk.rest.model.Event +import org.matrix.androidsdk.rest.model.RoomMember import org.matrix.androidsdk.rest.model.bingrules.BingRule +/** + * The notifiable event resolver is able to create a NotifiableEvent (view model for notifications) from an sdk Event. + * It is used as a bridge between the Event Thread and the NotificationDrawerManager. + * The NotifiableEventResolver is the only aware of session/store, the NotificationDrawerManager has no knowledge of that, + * this pattern allow decoupling between the object responsible of displaying notifications and the matrix sdk. + */ class NotifiableEventResolver(val context: Context) { private val eventDisplay = RiotEventDisplay(context) @@ -61,12 +69,12 @@ class NotifiableEventResolver(val context: Context) { timestamp = event.originServerTs, description = body, soundName = bingRule?.notificationSound, - title = "New Event", + title = context.getString(R.string.notification_unknown_new_event), type = event.type) } //Unsupported event - Log.i(LOG_TAG, "NotifiableEventResolver Received an unsupported event matching a bing rule") + Log.w(LOG_TAG, "NotifiableEventResolver Received an unsupported event matching a bing rule") return null } } @@ -81,7 +89,7 @@ class NotifiableEventResolver(val context: Context) { val room = store.getRoom(event.roomId /*roomID cannot be null (see Matrix SDK code)*/) if (room == null) { - Log.e(LOG_TAG, "## NotifiableEventResolver: Unable to resolve room for eventId [${event.eventId}] and roomID [${event.roomId}]") + Log.e(LOG_TAG, "## Unable to resolve room for eventId [${event.eventId}] and roomID [${event.roomId}]") return null } else { @@ -90,7 +98,7 @@ class NotifiableEventResolver(val context: Context) { return null } - val body = eventDisplay.getTextualDisplay(event, room.state)?.toString() ?: "New Event" + val body = eventDisplay.getTextualDisplay(event, room.state)?.toString() ?: context.getString(R.string.notification_unknown_new_event) val roomName = room.getRoomDisplayName(context) val senderDisplayName = room.state.getMemberName(event.sender) ?: event.sender ?: "" @@ -130,22 +138,22 @@ class NotifiableEventResolver(val context: Context) { } private fun resolveStateRoomEvent(event: Event, bingRule: BingRule?, session: MXSession, store: IMXStore): NotifiableEvent? { - if ("invite" == event.contentAsJsonObject?.getAsJsonPrimitive("membership")?.asString) { + if ("invite" == event.contentAsJsonObject?.getAsJsonPrimitive(RoomMember.MEMBERSHIP_INVITE)?.asString) { val room = store.getRoom(event.roomId /*roomID cannot be null (see Matrix SDK code)*/) - val body = eventDisplay.getTextualDisplay(event, room.state)?.toString() ?: "Invite" + val body = eventDisplay.getTextualDisplay(event, room.state)?.toString() ?: context.getString(R.string.notification_new_invitation) return InviteNotifiableEvent( session.myUserId, eventId = event.eventId, roomId = event.roomId, timestamp = event.originServerTs, noisy = bingRule?.notificationSound != null, - title = "New Invitation", + title = context.getString(R.string.notification_new_invitation), description = body, soundName = bingRule?.notificationSound, type = event.type, isPushGatewayEvent = false) } else { - Log.e(LOG_TAG, "## NotifiableEventResolver: unsupported notifiable event for eventId [${event.eventId}]") + Log.e(LOG_TAG, "## unsupported notifiable event for eventId [${event.eventId}]") //TODO generic handling? } return null diff --git a/vector/src/main/java/im/vector/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/notifications/NotificationDrawerManager.kt index 45fb5fe3b7..c56fb3647e 100644 --- a/vector/src/main/java/im/vector/notifications/NotificationDrawerManager.kt +++ b/vector/src/main/java/im/vector/notifications/NotificationDrawerManager.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018 New Vector Ltd + * Copyright 2019 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. @@ -23,34 +23,24 @@ import android.os.PowerManager import android.support.v4.app.NotificationCompat import android.text.TextUtils import android.view.WindowManager +import im.vector.BuildConfig import im.vector.Matrix import im.vector.R import im.vector.VectorApp import org.matrix.androidsdk.util.Log import java.io.* - -data class RoomEventGroupInfo( - val roomId: String -) { - var roomDisplayName: String = "" - var roomAvatarPath: String? = null - var hasNewEvent: Boolean = false //An event in the list has not yet been display - var shouldBing: Boolean = false //true if at least one on the not yet displayed event is noisy - var customSound: String? = null - var hasSmartReplyError = false -} - +/** + * The NotificationDrawerManager receives notification events as they arrived (from event stream or fcm) and + * organise them in order to display them in the notification drawer. + * Events can be grouped into the same notification, old (already read) events can be removed to do some cleaning. + */ class NotificationDrawerManager(val context: Context) { //The first time the notification drawer is refreshed, we force re-render of all notifications private var firstTime = true - init { - loadEventInfo() - } - - private lateinit var eventList: MutableList + private var eventList = loadEventInfo() private var myUserDisplayName: String = "" //Keeps a mapping between a notification ID @@ -70,7 +60,9 @@ class NotificationDrawerManager(val context: Context) { fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent, userId: String, userDisplayName: String?) { //If we support multi session, event list should be per userId //Currently only manage single session - Log.d(LOG_TAG, "%%%%%%%% onNotifiableEventReceived $notifiableEvent") + if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { + Log.d(LOG_TAG, "%%%%%%%% onNotifiableEventReceived $notifiableEvent") + } synchronized(this) { myUserDisplayName = userDisplayName ?: userId val existing = eventList.firstOrNull { it.eventId == notifiableEvent.eventId } @@ -217,7 +209,7 @@ class NotificationDrawerManager(val context: Context) { roomGroup.hasNewEvent = roomGroup.hasNewEvent || !event.hasBeenDisplayed //TODO update to compat-28 in order to support media and sender as a Person object if (event.outGoingMessage && event.outGoingMessageFailed) { - style.addMessage("** Failed to send - please open room", event.timestamp, event.senderName) + style.addMessage(context.getString(R.string.notification_inline_reply_failed), event.timestamp, event.senderName) roomGroup.hasSmartReplyError = true } else { style.addMessage(event.body, event.timestamp, event.senderName) @@ -287,10 +279,12 @@ class NotificationDrawerManager(val context: Context) { NotificationUtils.cancelNotificationMessage(context, null, SUMMARY_NOTIFICATION_ID) } else { val nbEvents = roomIdToEventMap.size + simpleEvents.size - summaryInboxStyle.setBigContentTitle("$nbEvents notifications") + val sumTitle = context.resources.getQuantityString( + R.plurals.notification_compat_summary_title, nbEvents, nbEvents) + summaryInboxStyle.setBigContentTitle(sumTitle) NotificationUtils.buildSummaryListNotification( context, - summaryInboxStyle, "$nbEvents notifications", + summaryInboxStyle, sumTitle, noisy = hasNewEvent && summaryIsNoisy )?.let { NotificationUtils.showNotificationMessage(context, null, SUMMARY_NOTIFICATION_ID, it) @@ -302,7 +296,7 @@ class NotificationDrawerManager(val context: Context) { if (Matrix.getInstance(VectorApp.getInstance())!!.pushManager.isScreenTurnedOn) { val pm = VectorApp.getInstance().getSystemService(Context.POWER_SERVICE) as PowerManager val wl = pm.newWakeLock(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or PowerManager.ACQUIRE_CAUSES_WAKEUP, - "riot:manageNotificationSound") + NotificationDrawerManager::class.java.name) wl.acquire(3000) wl.release() } @@ -337,7 +331,7 @@ class NotificationDrawerManager(val context: Context) { } private fun shouldIgnoreMessageEventInRoom(roomId: String?): Boolean { - return roomId != null && roomId == currentRoomId + return currentRoomId != null && roomId == currentRoomId } @@ -358,7 +352,7 @@ class NotificationDrawerManager(val context: Context) { } } - private fun loadEventInfo() { + private fun loadEventInfo(): ArrayList { try { val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME) if (file.exists()) { @@ -366,15 +360,13 @@ class NotificationDrawerManager(val context: Context) { val ois = ObjectInputStream(fileIn) val readObject = ois.readObject() (readObject as? ArrayList<*>)?.let { arrayList -> - this.eventList = ArrayList(arrayList.filter { it is NotifiableEvent }.mapNotNull { it as NotifiableEvent }) + return ArrayList(arrayList.mapNotNull { it as NotifiableEvent }) } - } else { - this.eventList = ArrayList() } } catch (e: Throwable) { - this.eventList = ArrayList() Log.e(LOG_TAG, "## Failed to load cached notification info", e) } + return ArrayList() } private fun deleteCachedRoomNotifications(context: Context) { diff --git a/vector/src/main/java/im/vector/notifications/NotificationUtils.kt b/vector/src/main/java/im/vector/notifications/NotificationUtils.kt index 36f51333c5..4aa4c4345d 100755 --- a/vector/src/main/java/im/vector/notifications/NotificationUtils.kt +++ b/vector/src/main/java/im/vector/notifications/NotificationUtils.kt @@ -80,13 +80,13 @@ object NotificationUtils { * IDs for actions * ========================================================================================== */ - private const val JOIN_ACTION = "NotificationUtils.JOIN_ACTION" - private const val REJECT_ACTION = "NotificationUtils.REJECT_ACTION" - private const val QUICK_LAUNCH_ACTION = "NotificationUtils.QUICK_LAUNCH_ACTION" - const val SMART_REPLY_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationUtils.SMART_REPLY_ACTION" + private const val JOIN_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationUtils.JOIN_ACTION" + private const val REJECT_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationUtils.REJECT_ACTION" + private const val QUICK_LAUNCH_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationUtils.QUICK_LAUNCH_ACTION" + const val SMART_REPLY_ACTION_PREFIX = "${BuildConfig.APPLICATION_ID}.NotificationUtils.SMART_REPLY_ACTION_" const val DISMISS_SUMMARY_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationUtils.DISMISS_SUMMARY_ACTION" const val DISMISS_ROOM_NOTIF_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationUtils.DISMISS_ROOM_NOTIF_ACTION" - const val TAP_TO_VIEW_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationUtils.TAP_TO_VIEW_ACTION" + private const val TAP_TO_VIEW_ACTION = "${BuildConfig.APPLICATION_ID}.NotificationUtils.TAP_TO_VIEW_ACTION" /* ========================================================================================== * IDs for channels @@ -332,372 +332,8 @@ object NotificationUtils { return builder.build() } - /** - * Add a text style to a notification when there are several notified rooms. - * - * @param context the context - * @param builder the notification builder - * @param roomsNotifications the rooms notifications - */ -// @Deprecated("will be removed") -// private fun addTextStyleWithSeveralRooms(context: Context, -// builder: NotificationCompat.Builder, -// roomsNotifications: RoomsNotifications) { -// val inboxStyle = NotificationCompat.InboxStyle() -// -// -// for (roomNotifications in roomsNotifications.mRoomNotifications) { -// val notifiedLine = SpannableString(roomNotifications.mMessagesSummary) -// notifiedLine.setSpan(StyleSpan(android.graphics.Typeface.BOLD), -// 0, roomNotifications.mMessageHeader.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) -// inboxStyle.addLine(notifiedLine) -// } -// -// inboxStyle.setBigContentTitle(context.getString(R.string.riot_app_name)) -// inboxStyle.setSummaryText(roomsNotifications.mSummaryText) -// builder.setStyle(inboxStyle) -// -// val stackBuilderTap = TaskStackBuilder.create(context) -// val roomIntentTap: Intent? -// -// // add the home page the activity stack -// stackBuilderTap.addNextIntentWithParentStack(Intent(context, VectorHomeActivity::class.java)) -// -// if (roomsNotifications.mIsInvitationEvent) { -// // for invitation the room preview must be displayed -// roomIntentTap = CommonActivityUtils.buildIntentPreviewRoom(roomsNotifications.mSessionId, -// roomsNotifications.mRoomId, context, VectorFakeRoomPreviewActivity::class.java) -// } else { -// roomIntentTap = Intent(context, VectorRoomActivity::class.java) -// roomIntentTap.putExtra(VectorRoomActivity.EXTRA_ROOM_ID, roomsNotifications.mRoomId) -// } -// -// roomIntentTap!!.action = TAP_TO_VIEW_ACTION -// stackBuilderTap.addNextIntent(roomIntentTap) -// builder.setContentIntent(stackBuilderTap.getPendingIntent(System.currentTimeMillis().toInt(), 0)) -// -// // offer to open the rooms list -// run { -// val openIntentTap = Intent(context, VectorHomeActivity::class.java) -// -// // Recreate the back stack -// val viewAllTask = TaskStackBuilder.create(context) -// .addNextIntent(openIntentTap) -// -// builder.addAction( -// R.drawable.ic_home_black_24dp, -// context.getString(R.string.bottom_action_home), -// viewAllTask.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)) -// } -// } - - /** - * Add a text style for a bunch of notified events. - * - * - * The notification contains the notified messages from any rooms. - * It does not contain anymore the latest notified message. - * - * - * When there is only one room, it displays the MAX_NUMBER_NOTIFICATION_LINES latest messages. - * The busy ones are displayed in RED. - * The QUICK REPLY and other buttons are displayed. - * - * - * When there are several rooms, it displays the busy notified rooms first (sorted by latest message timestamp). - * Each line is - * - "Room Name : XX unread messages" if there are many unread messages - * - 'Room Name : Sender - Message body" if there is only one unread message. - * - * @param context the context - * @param builder the notification builder - * @param roomsNotifications the rooms notifications - */ -// @Deprecated("will be removed") -// private fun addTextStyle(context: Context, -// builder: NotificationCompat.Builder, -// roomsNotifications: RoomsNotifications) { -// -// // nothing to do -// if (0 == roomsNotifications.mRoomNotifications.size) { -// return -// } -// -// // when there are several rooms, the text style is not the same -// if (roomsNotifications.mRoomNotifications.size > 1) { -// addTextStyleWithSeveralRooms(context, builder, roomsNotifications) -// return -// } -// -// var latestText: SpannableString? = null -// val inboxStyle = NotificationCompat.InboxStyle() -// -// for (sequence in roomsNotifications.mReversedMessagesList) { -// inboxStyle.addLine(SpannableString(sequence)) -// } -// -// inboxStyle.setBigContentTitle(roomsNotifications.mContentTitle) -// -// // adapt the notification display to the number of notified messages -// if (1 == roomsNotifications.mReversedMessagesList.size && null != latestText) { -// builder.setStyle(NotificationCompat.BigTextStyle().bigText(latestText)) -// } else { -// if (!TextUtils.isEmpty(roomsNotifications.mSummaryText)) { -// inboxStyle.setSummaryText(roomsNotifications.mSummaryText) -// } -// builder.setStyle(inboxStyle) -// } -// -// if (roomsNotifications.mIsInvitationEvent) { -// run { -// // offer to type a quick reject button -// val rejectIntent = JoinRoomActivity.getRejectRoomIntent(context, roomsNotifications.mRoomId, roomsNotifications.mSessionId) -// -// // the action must be unique else the parameters are ignored -// rejectIntent.action = REJECT_ACTION + System.currentTimeMillis().toInt() -// val pIntent = PendingIntent.getActivity(context, 0, rejectIntent, 0) -// builder.addAction( -// R.drawable.vector_notification_reject_invitation, -// context.getString(R.string.reject), -// pIntent) -// } -// -// run { -// // offer to type a quick accept button -// val joinIntent = JoinRoomActivity.getJoinRoomIntent(context, roomsNotifications.mRoomId, roomsNotifications.mSessionId) -// -// // the action must be unique else the parameters are ignored -// joinIntent.action = JOIN_ACTION + System.currentTimeMillis().toInt() -// val pIntent = PendingIntent.getActivity(context, 0, joinIntent, 0) -// builder.addAction( -// R.drawable.vector_notification_accept_invitation, -// context.getString(R.string.join), -// pIntent) -// } -// } else if (!LockScreenActivity.isDisplayingALockScreenActivity()) { -// // (do not offer to quick respond if the user did not dismiss the previous one) -// -// // offer to type a quick answer (i.e. without launching the application) -// val quickReplyIntent = Intent(context, LockScreenActivity::class.java) -// quickReplyIntent.putExtra(LockScreenActivity.EXTRA_ROOM_ID, roomsNotifications.mRoomId) -// quickReplyIntent.putExtra(LockScreenActivity.EXTRA_SENDER_NAME, roomsNotifications.mSenderName) -// quickReplyIntent.putExtra(LockScreenActivity.EXTRA_MESSAGE_BODY, roomsNotifications.mQuickReplyBody) -// -// // the action must be unique else the parameters are ignored -// quickReplyIntent.action = QUICK_LAUNCH_ACTION + System.currentTimeMillis().toInt() -// val pIntent = PendingIntent.getActivity(context, 0, quickReplyIntent, 0) -// builder.addAction( -// R.drawable.vector_notification_quick_reply, -// context.getString(R.string.action_quick_reply), -// pIntent) -// } -// -// // Build the pending intent for when the notification is clicked -// val roomIntentTap: Intent -// -// if (roomsNotifications.mIsInvitationEvent) { -// // for invitation the room preview must be displayed -// roomIntentTap = CommonActivityUtils.buildIntentPreviewRoom(roomsNotifications.mSessionId, -// roomsNotifications.mRoomId, context, VectorFakeRoomPreviewActivity::class.java) -// } else { -// roomIntentTap = Intent(context, VectorRoomActivity::class.java) -// roomIntentTap.putExtra(VectorRoomActivity.EXTRA_ROOM_ID, roomsNotifications.mRoomId) -// } -// // the action must be unique else the parameters are ignored -// roomIntentTap.action = TAP_TO_VIEW_ACTION + System.currentTimeMillis().toInt() -// -// // Recreate the back stack -// val stackBuilderTap = TaskStackBuilder.create(context) -// .addNextIntentWithParentStack(Intent(context, VectorHomeActivity::class.java)) -// .addNextIntent(roomIntentTap) -// -// builder.setContentIntent(stackBuilderTap.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)) -// -// builder.addAction( -// R.drawable.vector_notification_open, -// context.getString(R.string.action_open), -// stackBuilderTap.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)) -// -// // wearable -// if (!roomsNotifications.mIsInvitationEvent) { -// try { -// val wearableExtender = NotificationCompat.WearableExtender() -// val action = NotificationCompat.Action.Builder(R.drawable.logo_transparent, -// roomsNotifications.mWearableMessage, -// stackBuilderTap.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)) -// .build() -// wearableExtender.addAction(action) -// builder.extend(wearableExtender) -// } catch (e: Exception) { -// Log.e(LOG_TAG, "## addTextStyleWithSeveralRooms() : WearableExtender failed " + e.message, e) -// } -// } -// } - - /** - * Add the notification sound. - * - * @param context the context - * @param builder the notification builder - * @param isBackground true if the notification is a background one (e.g. read receipt) - * @param isBing true if the notification should play sound - */ - @SuppressLint("NewApi") - private fun manageNotificationSound(context: Context, builder: NotificationCompat.Builder, isBackground: Boolean, isBing: Boolean) { - @ColorInt val highlightColor = ContextCompat.getColor(context, R.color.vector_fuchsia_color) - - //set default, will be overridden if needed - builder.color = Color.TRANSPARENT - - if (isBackground) { // no event notification (like read receipt) - builder.priority = NotificationCompat.PRIORITY_LOW - builder.setChannelId(SILENT_NOTIFICATION_CHANNEL_ID) - } else { - builder.setDefaults(Notification.DEFAULT_LIGHTS) - - if (isBing) { - builder.setChannelId(NOISY_NOTIFICATION_CHANNEL_ID) - builder.color = highlightColor - //android , bingRule: BingRule): Notification? { -// try { -// -// val builder = NotificationCompat.Builder(context, SILENT_NOTIFICATION_CHANNEL_ID) -// .setWhen(System.currentTimeMillis()) -// .setContentTitle(context.getString(R.string.riot_app_name)) -// .setContentText(messagesStrings[0]) -// .setSmallIcon(R.drawable.logo_transparent) -// .setGroup(context.getString(R.string.riot_app_name)) -// .setGroupSummary(true) -// -// val inboxStyle = NotificationCompat.InboxStyle() -// -// for (i in 0 until Math.min(RoomsNotifications.MAX_NUMBER_NOTIFICATION_LINES, messagesStrings.size)) { -// inboxStyle.addLine(messagesStrings[i]) -// } -// -// inboxStyle.setBigContentTitle(context.getString(R.string.riot_app_name)) -// .setSummaryText( -// context.resources -// .getQuantityString(R.plurals.notification_unread_notified_messages, messagesStrings.size, messagesStrings.size)) -// -// builder.setStyle(inboxStyle) -// -// // open the home activity -// val stackBuilderTap = TaskStackBuilder.create(context) -// val roomIntentTap = Intent(context, VectorHomeActivity::class.java) -// roomIntentTap.action = TAP_TO_VIEW_ACTION + System.currentTimeMillis().toInt() -// stackBuilderTap.addNextIntent(roomIntentTap) -// -// builder.setContentIntent(stackBuilderTap.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)) -// -// manageNotificationSound(context, builder, false, BingRule.isDefaultNotificationSound(bingRule.notificationSound)) -// -// return builder.build() -// } catch (e: Exception) { -// Log.e(LOG_TAG, "## buildMessagesListNotification() : failed" + e.message, e) -// } -// -// return null -// } - - fun buildMessagesListNotification(context: Context, messageSytle: NotificationCompat.MessagingStyle, + fun buildMessagesListNotification(context: Context, + messageSytle: NotificationCompat.MessagingStyle, roomInfo: RoomEventGroupInfo, largeIcon: Bitmap?, senderDisplayNameForReplyCompat: String?): Notification? { @@ -708,84 +344,81 @@ object NotificationUtils { val smallIcon = if (roomInfo.shouldBing) R.drawable.icon_notif_important else R.drawable.logo_transparent val channelID = if (roomInfo.shouldBing) NOISY_NOTIFICATION_CHANNEL_ID else SILENT_NOTIFICATION_CHANNEL_ID - val builder = NotificationCompat.Builder(context, channelID) - builder.apply { - // MESSAGING_STYLE sets title and content for API 16 and above devices. - setStyle(messageSytle) + return NotificationCompat.Builder(context, channelID) + // MESSAGING_STYLE sets title and content for API 16 and above devices. + .setStyle(messageSytle) - // A category allows groups of notifications to be ranked and filtered – per user or system settings. - // For example, alarm notifications should display before promo notifications, or message from known contact - // that can be displayed in not disturb mode if white listed (the later will need compat28.x) - setCategory(Notification.CATEGORY_MESSAGE) + // A category allows groups of notifications to be ranked and filtered – per user or system settings. + // For example, alarm notifications should display before promo notifications, or message from known contact + // that can be displayed in not disturb mode if white listed (the later will need compat28.x) + .setCategory(Notification.CATEGORY_MESSAGE) - // Title for API < 16 devices. - setContentTitle(roomInfo.roomDisplayName) - // Content for API < 16 devices. - setContentText("New Messages") //TODO + // Title for API < 16 devices. + .setContentTitle(roomInfo.roomDisplayName) + // Content for API < 16 devices. + .setContentText(context.getString(R.string.notification_new_messages)) - // Number of new notifications for API <24 (M and below) devices. - setSubText(context.resources.getQuantityString(R.plurals.room_new_messages_notification,messageSytle.messages.size,messageSytle.messages.size)) + // Number of new notifications for API <24 (M and below) devices. + .setSubText(context.resources.getQuantityString(R.plurals.room_new_messages_notification, messageSytle.messages.size, messageSytle.messages.size)) - // Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) - // devices and all Wear devices. But we want a custom grouping, so we specify the groupID - setGroup(context.getString(R.string.riot_app_name)) + // Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) + // devices and all Wear devices. But we want a custom grouping, so we specify the groupID + .setGroup(context.getString(R.string.riot_app_name)) - //In order to avoid notification making sound twice (due to the summary notificaiton) - setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) + //In order to avoid notification making sound twice (due to the summary notificaiton) + .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) - setSmallIcon(smallIcon) - - // Set primary color (important for Wear 2.0 Notifications). - color = accentColor + .setSmallIcon(smallIcon) - // Sets priority for 25 and below. For 26 and above, 'priority' is deprecated for - // 'importance' which is set in the NotificationChannel. The integers representing - // 'priority' are different from 'importance', so make sure you don't mix them. - priority = NotificationCompat.PRIORITY_DEFAULT - if (roomInfo.shouldBing) { - //Compat - PreferencesManager.getNotificationRingTone(context)?.let { - setSound(it) - } - setLights(accentColor, 500, 500) - } else { - priority = NotificationCompat.PRIORITY_LOW - } + // Set primary color (important for Wear 2.0 Notifications). + .setColor(accentColor) - //Add actions and notification intents + // Sets priority for 25 and below. For 26 and above, 'priority' is deprecated for + // 'importance' which is set in the NotificationChannel. The integers representing + // 'priority' are different from 'importance', so make sure you don't mix them. + .apply { + priority = NotificationCompat.PRIORITY_DEFAULT + if (roomInfo.shouldBing) { + //Compat + PreferencesManager.getNotificationRingTone(context)?.let { + setSound(it) + } + setLights(accentColor, 500, 500) + } else { + priority = NotificationCompat.PRIORITY_LOW + } - if (!roomInfo.hasSmartReplyError) { - buildQuickReplyIntent(context, roomInfo.roomId, senderDisplayNameForReplyCompat)?.let { replyPendingIntent -> - var replyLabel: String = context.getString(R.string.action_quick_reply) - var remoteInput: RemoteInput = RemoteInput.Builder(NotificationBroadcastReceiver.KEY_TEXT_REPLY).run { - setLabel(replyLabel) - build() + //Add actions and notification intents + + if (!roomInfo.hasSmartReplyError) { + buildQuickReplyIntent(context, roomInfo.roomId, senderDisplayNameForReplyCompat)?.let { replyPendingIntent -> + var remoteInput = RemoteInput.Builder(NotificationBroadcastReceiver.KEY_TEXT_REPLY) + .setLabel(context.getString(R.string.action_quick_reply)) + .build() + NotificationCompat.Action.Builder(R.drawable.vector_notification_quick_reply, + context.getString(R.string.action_quick_reply), replyPendingIntent) + .addRemoteInput(remoteInput) + .build()?.let { + addAction(it) + } + } } - NotificationCompat.Action.Builder(R.drawable.vector_notification_quick_reply, - context.getString(R.string.action_quick_reply), replyPendingIntent) - .addRemoteInput(remoteInput) - .build()?.let { - addAction(it) - } - } - } - if (openRoomIntent != null) { - setContentIntent(openRoomIntent) - } + if (openRoomIntent != null) { + setContentIntent(openRoomIntent) + } - if (largeIcon != null) { - setLargeIcon(largeIcon) - } + if (largeIcon != null) { + setLargeIcon(largeIcon) + } - val intent = Intent(context, NotificationBroadcastReceiver::class.java) - intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomInfo.roomId) - intent.action = DISMISS_ROOM_NOTIF_ACTION - val pendingIntent = PendingIntent.getBroadcast(context.applicationContext, - System.currentTimeMillis().toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) - setDeleteIntent(pendingIntent) - } - return builder.build() + val intent = Intent(context, NotificationBroadcastReceiver::class.java) + intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomInfo.roomId) + intent.action = DISMISS_ROOM_NOTIF_ACTION + val pendingIntent = PendingIntent.getBroadcast(context.applicationContext, + System.currentTimeMillis().toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) + setDeleteIntent(pendingIntent) + }.build() } @@ -837,7 +470,7 @@ object NotificationUtils { val contentIntent = Intent(context, VectorHomeActivity::class.java) contentIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP //pending intent get reused by system, this will mess up the extra params, so put unique info to avoid that - contentIntent.data = Uri.parse("foobar://"+simpleNotifiableEvent.eventId) + contentIntent.data = Uri.parse("foobar://" + simpleNotifiableEvent.eventId) setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, 0)) if (largeIcon != null) { @@ -899,7 +532,7 @@ object NotificationUtils { val intent: Intent if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent = Intent(context, NotificationBroadcastReceiver::class.java) - intent.action = "${SMART_REPLY_ACTION}_$roomId" + intent.action = "${SMART_REPLY_ACTION_PREFIX}_$roomId" intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) return PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) @@ -919,12 +552,12 @@ object NotificationUtils { } //// Number of new notifications for API <24 (M and below) devices. - fun buildSummaryListNotification(context: Context, inboxSytle: NotificationCompat.InboxStyle, compatSummary: String, noisy: Boolean): Notification? { + fun buildSummaryListNotification(context: Context, sytle: NotificationCompat.Style, compatSummary: String, noisy: Boolean): Notification? { val smallIcon = if (noisy) R.drawable.icon_notif_important else R.drawable.logo_transparent - val builder = NotificationCompat.Builder(context, if (noisy) NOISY_NOTIFICATION_CHANNEL_ID else SILENT_NOTIFICATION_CHANNEL_ID) - .setStyle(inboxSytle) // used in compat < N, after summary is built based on child notifications + return NotificationCompat.Builder(context, if (noisy) NOISY_NOTIFICATION_CHANNEL_ID else SILENT_NOTIFICATION_CHANNEL_ID) + .setStyle(sytle) // used in compat < N, after summary is built based on child notifications .setContentTitle(context.getString(R.string.riot_app_name)) .setSmallIcon(smallIcon) //set content text to support devices running API level < 24 @@ -944,12 +577,10 @@ object NotificationUtils { //compat priority = NotificationCompat.PRIORITY_LOW } - - setContentIntent(buildOpenHomePendingIntentForSummary(context)) - setDeleteIntent(getDismissSummaryPendingIntent(context)) - } - return builder.build() + .setContentIntent(buildOpenHomePendingIntentForSummary(context)) + .setDeleteIntent(getDismissSummaryPendingIntent(context)) + .build() } diff --git a/vector/src/main/java/im/vector/notifications/RoomEventGroupInfo.kt b/vector/src/main/java/im/vector/notifications/RoomEventGroupInfo.kt new file mode 100644 index 0000000000..16cb78b763 --- /dev/null +++ b/vector/src/main/java/im/vector/notifications/RoomEventGroupInfo.kt @@ -0,0 +1,15 @@ +package im.vector.notifications + +/** + * Data class to old information about a group of notification for a room + */ +data class RoomEventGroupInfo( + val roomId: String +) { + var roomDisplayName: String = "" + var roomAvatarPath: String? = null + var hasNewEvent: Boolean = false //An event in the list has not yet been display + var shouldBing: Boolean = false //true if at least one on the not yet displayed event is noisy + var customSound: String? = null + var hasSmartReplyError = false +} \ No newline at end of file diff --git a/vector/src/main/java/im/vector/receiver/NotificationBroadcastReceiver.kt b/vector/src/main/java/im/vector/receiver/NotificationBroadcastReceiver.kt index fe35bc0043..f5bcefd23c 100644 --- a/vector/src/main/java/im/vector/receiver/NotificationBroadcastReceiver.kt +++ b/vector/src/main/java/im/vector/receiver/NotificationBroadcastReceiver.kt @@ -1,15 +1,12 @@ -/** +/* * Copyright 2019 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. @@ -26,6 +23,7 @@ import android.support.v4.app.RemoteInput import android.text.TextUtils import android.widget.Toast import im.vector.Matrix +import im.vector.R import im.vector.VectorApp import im.vector.notifications.NotifiableMessageEvent import im.vector.notifications.NotificationUtils @@ -38,6 +36,9 @@ import org.matrix.androidsdk.rest.model.MatrixError import org.matrix.androidsdk.rest.model.message.Message import org.matrix.androidsdk.util.Log +/** + * Receives actions broadcasted by notification (on click, on dismiss, inline replies) + */ class NotificationBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { @@ -45,7 +46,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { Log.d(LOG_TAG, "ReplyNotificationBroadcastReceiver received : $intent") val action = intent.action if (action != null) { - if (action.startsWith(NotificationUtils.SMART_REPLY_ACTION)) { + if (action.startsWith(NotificationUtils.SMART_REPLY_ACTION_PREFIX)) { handleSmartReply(intent, context) } else if (action == NotificationUtils.DISMISS_ROOM_NOTIF_ACTION) { intent.getStringExtra(KEY_ROOM_ID)?.let { @@ -90,7 +91,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { false, System.currentTimeMillis(), session.myUser?.displayname - ?: "", + ?: context?.getString(R.string.notification_sender_me), message, roomId, room.getRoomDisplayName(context)) @@ -128,7 +129,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() { false, System.currentTimeMillis(), session.myUser?.displayname - ?: "", + ?: context?.getString(R.string.notification_sender_me), message, roomId, room.getRoomDisplayName(context)) diff --git a/vector/src/main/java/im/vector/services/EventStreamService.java b/vector/src/main/java/im/vector/services/EventStreamService.java index 22caf81b3f..3c3bad788d 100755 --- a/vector/src/main/java/im/vector/services/EventStreamService.java +++ b/vector/src/main/java/im/vector/services/EventStreamService.java @@ -45,7 +45,6 @@ import org.matrix.androidsdk.listeners.MXEventListener; import org.matrix.androidsdk.rest.model.Event; import org.matrix.androidsdk.rest.model.bingrules.BingRule; -import org.matrix.androidsdk.util.BingRulesManager; import org.matrix.androidsdk.util.Log; import java.util.ArrayList; @@ -53,6 +52,7 @@ import java.util.List; import java.util.Random; +import im.vector.BuildConfig; import im.vector.Matrix; import im.vector.R; import im.vector.VectorApp; @@ -178,23 +178,15 @@ public static EventStreamService getInstance() { return mActiveEventStreamService; } - /** - * Track bing rules updates - */ - private final BingRulesManager.onBingRulesUpdateListener mBingRulesUpdatesListener = new BingRulesManager.onBingRulesUpdateListener() { - @Override - public void onBingRulesUpdate() { - - } - }; - /** * Live events listener */ private final MXEventListener mEventsListener = new MXEventListener() { @Override public void onBingEvent(Event event, RoomState roomState, BingRule bingRule) { - Log.d(LOG_TAG, "%%%%%%%% MXEventListener: the event " + event); + if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { + Log.d(LOG_TAG, "%%%%%%%% MXEventListener: the event " + event); + } // privacy //Log.d(LOG_TAG, "onBingEvent : the event " + event); //Log.d(LOG_TAG, "onBingEvent : the bingRule " + bingRule); @@ -295,7 +287,6 @@ public void stopAccounts(List matrixIds) { if (null != session) { session.stopEventStream(); session.getDataHandler().removeListener(mEventsListener); - session.getDataHandler().getBingRulesManager().removeBingRulesUpdateListener(mBingRulesUpdatesListener); CallsManager.getSharedInstance().removeSession(session); mSessions.remove(session); mMatrixIds.remove(matrixId); @@ -546,7 +537,6 @@ public static boolean isStopped() { */ private void monitorSession(final MXSession session) { session.getDataHandler().addListener(mEventsListener); - session.getDataHandler().getBingRulesManager().addBingRulesUpdateListener(mBingRulesUpdatesListener); CallsManager.getSharedInstance().addSession(session); session.getDataHandler().addListener(new MXEventListener() { @@ -684,7 +674,6 @@ private void stop() { if (null != session && session.isAlive()) { session.stopEventStream(); session.getDataHandler().removeListener(mEventsListener); - session.getDataHandler().getBingRulesManager().removeBingRulesUpdateListener(mBingRulesUpdatesListener); CallsManager.getSharedInstance().removeSession(session); } } @@ -999,7 +988,7 @@ else if (null == CallsManager.getSharedInstance().getActiveCall()) { Notification notification = NotificationUtils.INSTANCE.buildIncomingCallNotification( EventStreamService.this, isVideo, - room.getRoomDisplayName(this)/*RoomsNotifications.getRoomName(getApplicationContext(), session, room, event)*/, + room.getRoomDisplayName(this), session.getMyUserId(), callId); setForegroundNotificationState(ForegroundNotificationState.INCOMING_CALL, notification); @@ -1012,7 +1001,7 @@ else if (null == CallsManager.getSharedInstance().getActiveCall()) { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wl = pm.newWakeLock( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | PowerManager.ACQUIRE_CAUSES_WAKEUP, - "riot:MXEventListener"); + EventStreamService.class.getSimpleName()); wl.acquire(3000); wl.release(); } catch (RuntimeException re) { diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 759bd2e4ac..9df4779b9b 100755 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -1026,8 +1026,17 @@ %1$s: 1 message %1$s: %2$d messages + + %d notification + %d notifications + %1$s in %2$s" + New Event + New Messages + New Invitation + Me + ** Failed to send - please open room Search for historical