Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom sound for Android Push Notification not working (FCM)

I have push notifications working using FCM from a cloud function. This works for both iOS and Android and displays the appropriate icon and plays a custom sound on iOS.

All is working except the custom sound for Android, it simply plays the default sound.

I have created a folder and added my sound file to it as follows: android\app\src\main\res\raw\mp3_example.mp3

This mp3 is 27s long. I have also tried a .wav and .aiff.

I read that I may have to create a push notification channel for later versions of Android so it could be related to this. I tried creating a channel and using the channelID from the cloud function and it works but there is no sound just a vibration.

The test device is a Moto G6 running Android 8. I am using: FCM Firebase Cloud Functions Ionic 4 Capacitor https://github.com/stewwan/capacitor-fcm

Cloud Function:

const notification: admin.messaging.Notification = {
      title: title,
      body: body
  }

  const message: admin.messaging.Message = {
    notification,
    topic: 'QMTBC',
    android:{
      notification:{
        sound: 'mp3_example.mp3',
        icon: 'push_logo',
        color: '#000000'
      }
    },
    apns:{
        payload:{
          aps: {
            sound: 'gears-short.wav'
          }
        }
    }
  }

  return admin.messaging().send(message)

app.component.ts

import { FCM } from 'capacitor-fcm';

const fcm = new FCM();
const { PushNotifications } = Plugins;

initializeApp() {
    this.platform.ready().then(() => {

      PushNotifications.register();

      PushNotifications.addListener('registration', (token: PushNotificationToken) => {
        console.log('token ' + token.value);
        fcm
        .subscribeTo({ topic: 'QMTBC' })
        .then(r => console.log(`subscribed to topic`))
        .catch(err => console.log(err));        
      });

      PushNotifications.addListener('registrationError', (error: any) => {
        console.log('error on register ' + JSON.stringify(error));
      });

      PushNotifications.addListener('pushNotificationReceived', (notification: PushNotification) => {
        console.log('notification ' + JSON.stringify(notification));
        this.pushNotificationService.notifications.push(notification);
      });

      PushNotifications.addListener('pushNotificationActionPerformed', (notification: PushNotificationActionPerformed) => {
        console.log('notification ' + JSON.stringify(notification));
        this.pushNotificationService.notifications.push(notification);
      });

      fcm.getToken()
        .then(r => console.log(`Token ${r.token}`))
        .catch(err => console.log(err));
    });
  }

UPDATE:

I tried creating a channel as follows. If I use the channel I just get the default sound. If I specific no channel or one that does not exist I also get the default sound (default channel).

cloud function:

const message: admin.messaging.Message = {
    notification,
    topic: 'QMTBC',
    android:{
      notification:{
        sound: 'punch.mp3',
        icon: 'push_logo',
        color: '#000000',
        channelId: 'QMTBC'
      }
    }

app.component.ts

const channel: PushNotificationChannel = {
          description: 'QMTBC',
          id : 'QMTBC',
          importance: 5,
          name : 'QMTBC'
        };

        PushNotifications.createChannel(channel).then(channelResult => {
          console.log(channelResult);
          console.log('Channel created');
          // PushNotifications.listChannels().then(channels => {
          //   console.log('Channels');
          //   console.log(channels);
          // });
        }, err => {
          console.log('Error Creating channel');
          console.log(err);
        });
      });

UPDATE 2:

I can see the channel I have created for the app on my device and it says the sound is default. I can manually change it to another inbuilt android sound and this works. But I still can't use my custom sound.

UPDATE 3:

The custom sound works on if the Android version is < 8. Only tested this on an emulator.

like image 486
MadMac Avatar asked Sep 07 '19 03:09

MadMac


2 Answers

@MadMac I was facing the same problem these days, after read FCM documentations and the Capacitor Java code, I got it.

It's necessary to set the visibility to 1, place your file in res/raw folder.

PushNotifications.createChannel({
            description: 'General Notifications',
            id: 'fcm_default_channel',
            importance: 5,
            lights: true,
            name: 'My notification channel',
            sound: 'notifications.wav',
            vibration: true,
            visibility: 1
        }).then(()=>{
            console.log('push channel created: ');
        }).catch(error =>{
            console.error('push channel error: ', error);
        });

I'm using this payload in my firestore function to send notifications

{
            android: {
                notification: {
                    defaultSound: true,
                    notificationCount: 1,
                    sound: 'notifications.wav',
                    channelId: 'fcm_default_channel'
                },
                ttl: 20000,
                collapseKey
            },
            apns: {
                payload: {
                    aps: {
                        badge: 1,
                        sound: 'default'
                    }
                }
            },
            notification: {
                title,
                body: message,
            },
            token: token
        };
like image 147
ThonyFD Avatar answered Oct 10 '22 16:10

ThonyFD


This was such a good question that helped me find the answer. So I post my answer here. Try setting the sound of the notifications to notification channels themselves at the time when you create the channels. I suppose, based on your info, the old Android versions will play sound according to the sound field in the notification payload, but in the new versions you would have to set it directly to the notification channels themselves since that is where the control is now currently intended to be by Google. I had to uninstall and reinstall the app for this code change to work, because my channels were previously initialized and the channels won't update after the first initialization.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !notificationChannelsInitialized) {
            val newMessagesChannel = NotificationChannel(NEW_MESSAGES_NOTIFICATION_CHANNEL_ID, "New Messages", NotificationManager.IMPORTANCE_HIGH)

            val notificationSoundUri =
                Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE.toString() + "://" + context.packageName + "/" + R.raw.ns) // ns.wav is my notification sound file in the res/raw folder in Android Studio
            val notificationSoundUriAttributes = AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                .build()
            newMessagesChannel.setSound(notificationSoundUri, notificationSoundUriAttributes)

            val notificationManager: NotificationManager =
                context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannels(listOf( newMessagesChannel)) // and other channels
        }
like image 1
coolcool1994 Avatar answered Oct 10 '22 15:10

coolcool1994