From eb6e6849dd0e967af91aebc2fc6b5d1d023b9452 Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Mon, 19 Feb 2024 17:12:31 +0100 Subject: [PATCH 1/5] fix: overwrite system sound for push notifications via a custom one --- .../CustomNotificationProvider.java | 17 +++++++++++++++++ .../NotificationService.swift | 2 ++ src/libs/actions/User.ts | 10 ++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index c57819d19d03..88f7f41c07dd 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -15,6 +15,8 @@ import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; +import android.media.AudioAttributes; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.service.notification.StatusBarNotification; @@ -31,6 +33,7 @@ import androidx.core.graphics.drawable.IconCompat; import androidx.versionedparcelable.ParcelUtils; +import com.expensify.chat.R; import com.urbanairship.AirshipConfigOptions; import com.urbanairship.json.JsonMap; import com.urbanairship.json.JsonValue; @@ -106,6 +109,9 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ builder.setPriority(PRIORITY_MAX); } + // Set sound for versions below Oreo + builder.setSound(getSoundFile(context)); + // Attempt to parse data and apply custom notification styling if (message.containsKey(PAYLOAD_KEY)) { try { @@ -129,6 +135,13 @@ private void createAndRegisterNotificationChannel(@NonNull Context context) { NotificationChannelGroup channelGroup = new NotificationChannelGroup(NOTIFICATION_GROUP_CHATS, CHANNEL_GROUP_NAME); NotificationChannel channel = new NotificationChannel(CHANNEL_MESSAGES_ID, CHANNEL_MESSAGES_NAME, NotificationManager.IMPORTANCE_HIGH); + AudioAttributes audioAttributes = new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_NOTIFICATION) + .build(); + + channel.setSound(getSoundFile(context), audioAttributes); + NotificationManager notificationManager = context.getSystemService(NotificationManager.class); notificationManager.createNotificationChannelGroup(channelGroup); notificationManager.createNotificationChannel(channel); @@ -332,4 +345,8 @@ private Bitmap fetchIcon(@NonNull Context context, String urlString) { return null; } + + private Uri getSoundFile(Context context) { + return Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.receive); + } } diff --git a/ios/NotificationServiceExtension/NotificationService.swift b/ios/NotificationServiceExtension/NotificationService.swift index c4eb01981bf2..e489cb368d17 100644 --- a/ios/NotificationServiceExtension/NotificationService.swift +++ b/ios/NotificationServiceExtension/NotificationService.swift @@ -24,6 +24,8 @@ class NotificationService: UANotificationServiceExtension { return } + bestAttemptContent.sound = UNNotificationSound(named: UNNotificationSoundName("receive.mp3")) + if #available(iOSApplicationExtension 15.0, *) { configureCommunicationNotification(notificationContent: bestAttemptContent, contentHandler: contentHandler) } else { diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index 75c61d7fab5f..7f38dface32b 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -1,4 +1,5 @@ import {isBefore} from 'date-fns'; +import {Platform} from 'react-native'; import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; @@ -550,8 +551,13 @@ function playSoundForMessageType(pushJSON: OnyxServerUpdate[]) { return playSound(SOUNDS.SUCCESS); } - // plain message - if ('html' in message) { + if ( + // plain message + 'html' in message && + // exclude mobile platforms, since they play sound when notification is delivered (in native code) + Platform.OS !== 'android' && + Platform.OS !== 'ios' + ) { return playSound(SOUNDS.RECEIVE); } } From 5f14d6200ae0a159340ef09cc6975fc32c8c27f8 Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Mon, 19 Feb 2024 18:10:03 +0100 Subject: [PATCH 2/5] chore: changes after code review --- .../customairshipextender/CustomNotificationProvider.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index 88f7f41c07dd..c7914bef83bc 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -107,11 +107,11 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ builder.setChannelId(CHANNEL_MESSAGES_ID); } else { builder.setPriority(PRIORITY_MAX); + // Set sound for versions below Oreo + // for Oreo and above we set sound on the notification's channel level + builder.setSound(getSoundFile(context)); } - // Set sound for versions below Oreo - builder.setSound(getSoundFile(context)); - // Attempt to parse data and apply custom notification styling if (message.containsKey(PAYLOAD_KEY)) { try { From e38e062ac011504093fb6070ba54673c097cf83d Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Tue, 20 Feb 2024 15:04:19 +0100 Subject: [PATCH 3/5] chore: changes after code review --- src/libs/Sound/playReceiveSound/index.native.ts | 2 ++ src/libs/Sound/playReceiveSound/index.ts | 5 +++++ src/libs/actions/User.ts | 13 ++++--------- 3 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 src/libs/Sound/playReceiveSound/index.native.ts create mode 100644 src/libs/Sound/playReceiveSound/index.ts diff --git a/src/libs/Sound/playReceiveSound/index.native.ts b/src/libs/Sound/playReceiveSound/index.native.ts new file mode 100644 index 000000000000..7ef23e2cefe6 --- /dev/null +++ b/src/libs/Sound/playReceiveSound/index.native.ts @@ -0,0 +1,2 @@ +// mobile platform plays a sound when notification is delivered (in native code) +export default function playReceiveSound() {} diff --git a/src/libs/Sound/playReceiveSound/index.ts b/src/libs/Sound/playReceiveSound/index.ts new file mode 100644 index 000000000000..bc808ac3262d --- /dev/null +++ b/src/libs/Sound/playReceiveSound/index.ts @@ -0,0 +1,5 @@ +import playSound, {SOUNDS} from '..'; + +export default function playReceiveSound() { + return playSound(SOUNDS.RECEIVE); +} diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index 7f38dface32b..655db228e2f4 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -1,5 +1,4 @@ import {isBefore} from 'date-fns'; -import {Platform} from 'react-native'; import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; @@ -30,6 +29,7 @@ import * as Pusher from '@libs/Pusher/pusher'; import PusherUtils from '@libs/PusherUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import playSound, {SOUNDS} from '@libs/Sound'; +import playReceiveSound from '@libs/Sound/playReceiveSound'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -551,14 +551,9 @@ function playSoundForMessageType(pushJSON: OnyxServerUpdate[]) { return playSound(SOUNDS.SUCCESS); } - if ( - // plain message - 'html' in message && - // exclude mobile platforms, since they play sound when notification is delivered (in native code) - Platform.OS !== 'android' && - Platform.OS !== 'ios' - ) { - return playSound(SOUNDS.RECEIVE); + // plain message + if ('html' in message) { + return playReceiveSound(); } } } catch (e) { From e140633e9ff53fe72cc25ae945a94bd507a99e91 Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Wed, 21 Feb 2024 13:08:59 +0100 Subject: [PATCH 4/5] fix: don't play sound on mobile when someone mentions you or entire channel --- src/libs/Sound/playReceiveSound/index.ts | 5 ----- .../index.native.ts | 2 +- src/libs/Sound/playSoundOnWebOnly/index.ts | 5 +++++ src/libs/actions/User.ts | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) delete mode 100644 src/libs/Sound/playReceiveSound/index.ts rename src/libs/Sound/{playReceiveSound => playSoundOnWebOnly}/index.native.ts (62%) create mode 100644 src/libs/Sound/playSoundOnWebOnly/index.ts diff --git a/src/libs/Sound/playReceiveSound/index.ts b/src/libs/Sound/playReceiveSound/index.ts deleted file mode 100644 index bc808ac3262d..000000000000 --- a/src/libs/Sound/playReceiveSound/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import playSound, {SOUNDS} from '..'; - -export default function playReceiveSound() { - return playSound(SOUNDS.RECEIVE); -} diff --git a/src/libs/Sound/playReceiveSound/index.native.ts b/src/libs/Sound/playSoundOnWebOnly/index.native.ts similarity index 62% rename from src/libs/Sound/playReceiveSound/index.native.ts rename to src/libs/Sound/playSoundOnWebOnly/index.native.ts index 7ef23e2cefe6..4a1bf0feff8f 100644 --- a/src/libs/Sound/playReceiveSound/index.native.ts +++ b/src/libs/Sound/playSoundOnWebOnly/index.native.ts @@ -1,2 +1,2 @@ // mobile platform plays a sound when notification is delivered (in native code) -export default function playReceiveSound() {} +export default function playSoundOnWebOnly() {} diff --git a/src/libs/Sound/playSoundOnWebOnly/index.ts b/src/libs/Sound/playSoundOnWebOnly/index.ts new file mode 100644 index 000000000000..716911d0bc14 --- /dev/null +++ b/src/libs/Sound/playSoundOnWebOnly/index.ts @@ -0,0 +1,5 @@ +import playSound from '..'; + +const playSoundOnWebOnly: typeof playSound = (sound) => playSound(sound); + +export default playSoundOnWebOnly; diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index 655db228e2f4..4b6ae67fd5fd 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -29,7 +29,7 @@ import * as Pusher from '@libs/Pusher/pusher'; import PusherUtils from '@libs/PusherUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import playSound, {SOUNDS} from '@libs/Sound'; -import playReceiveSound from '@libs/Sound/playReceiveSound'; +import playSoundOnWebOnly from '@libs/Sound/playSoundOnWebOnly'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -528,12 +528,12 @@ function playSoundForMessageType(pushJSON: OnyxServerUpdate[]) { // mention user if ('html' in message && typeof message.html === 'string' && message.html.includes('')) { - return playSound(SOUNDS.ATTENTION); + return playSoundOnWebOnly(SOUNDS.ATTENTION); } // mention @here if ('html' in message && typeof message.html === 'string' && message.html.includes('')) { - return playSound(SOUNDS.ATTENTION); + return playSoundOnWebOnly(SOUNDS.ATTENTION); } // assign a task @@ -553,7 +553,7 @@ function playSoundForMessageType(pushJSON: OnyxServerUpdate[]) { // plain message if ('html' in message) { - return playReceiveSound(); + return playSoundOnWebOnly(SOUNDS.RECEIVE); } } } catch (e) { From 9e9476eb3ee5a6cb7361f6a0d488ceb6dd10c6f5 Mon Sep 17 00:00:00 2001 From: kirillzyusko Date: Wed, 21 Feb 2024 17:40:10 +0100 Subject: [PATCH 5/5] refactor: playSoundOnWebOnly -> playSoundExcludingMobile --- .../index.native.ts | 2 +- src/libs/Sound/playSoundExcludingMobile/index.ts | 5 +++++ src/libs/Sound/playSoundOnWebOnly/index.ts | 5 ----- src/libs/actions/User.ts | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) rename src/libs/Sound/{playSoundOnWebOnly => playSoundExcludingMobile}/index.native.ts (60%) create mode 100644 src/libs/Sound/playSoundExcludingMobile/index.ts delete mode 100644 src/libs/Sound/playSoundOnWebOnly/index.ts diff --git a/src/libs/Sound/playSoundOnWebOnly/index.native.ts b/src/libs/Sound/playSoundExcludingMobile/index.native.ts similarity index 60% rename from src/libs/Sound/playSoundOnWebOnly/index.native.ts rename to src/libs/Sound/playSoundExcludingMobile/index.native.ts index 4a1bf0feff8f..c41ad6998483 100644 --- a/src/libs/Sound/playSoundOnWebOnly/index.native.ts +++ b/src/libs/Sound/playSoundExcludingMobile/index.native.ts @@ -1,2 +1,2 @@ // mobile platform plays a sound when notification is delivered (in native code) -export default function playSoundOnWebOnly() {} +export default function playSoundExcludingMobile() {} diff --git a/src/libs/Sound/playSoundExcludingMobile/index.ts b/src/libs/Sound/playSoundExcludingMobile/index.ts new file mode 100644 index 000000000000..03c5cd57a635 --- /dev/null +++ b/src/libs/Sound/playSoundExcludingMobile/index.ts @@ -0,0 +1,5 @@ +import playSound from '..'; + +const playSoundExcludingMobile: typeof playSound = (sound) => playSound(sound); + +export default playSoundExcludingMobile; diff --git a/src/libs/Sound/playSoundOnWebOnly/index.ts b/src/libs/Sound/playSoundOnWebOnly/index.ts deleted file mode 100644 index 716911d0bc14..000000000000 --- a/src/libs/Sound/playSoundOnWebOnly/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -import playSound from '..'; - -const playSoundOnWebOnly: typeof playSound = (sound) => playSound(sound); - -export default playSoundOnWebOnly; diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index 4b88ae4ee6a1..8c0864d22791 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -29,7 +29,7 @@ import * as Pusher from '@libs/Pusher/pusher'; import PusherUtils from '@libs/PusherUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import playSound, {SOUNDS} from '@libs/Sound'; -import playSoundOnWebOnly from '@libs/Sound/playSoundOnWebOnly'; +import playSoundExcludingMobile from '@libs/Sound/playSoundExcludingMobile'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -528,12 +528,12 @@ function playSoundForMessageType(pushJSON: OnyxServerUpdate[]) { // mention user if ('html' in message && typeof message.html === 'string' && message.html.includes(`@${currentEmail}`)) { - return playSoundOnWebOnly(SOUNDS.ATTENTION); + return playSoundExcludingMobile(SOUNDS.ATTENTION); } // mention @here if ('html' in message && typeof message.html === 'string' && message.html.includes('')) { - return playSoundOnWebOnly(SOUNDS.ATTENTION); + return playSoundExcludingMobile(SOUNDS.ATTENTION); } // assign a task @@ -553,7 +553,7 @@ function playSoundForMessageType(pushJSON: OnyxServerUpdate[]) { // plain message if ('html' in message) { - return playSoundOnWebOnly(SOUNDS.RECEIVE); + return playSoundExcludingMobile(SOUNDS.RECEIVE); } } } catch (e) {