ali
ali

Reputation: 969

Firebase push notification with custom sound (Flutter)

I'm currently using firebase messaging cloud to push notification for my app. I'm trying to make a custom notification sound for the push notification. I believe that it can be done by putting "sound: blabla.mp3" inside the payload, but how do i define the sound inside dart page?

Upvotes: 14

Views: 24732

Answers (5)

K.Amanov
K.Amanov

Reputation: 1618

It can be done flutter_local_notifications plugin.

First, you should define channels for both Android and iOS:

const androidPlatformChannel = AndroidNotificationDetails(
  'ANDROID_CHANNEL_ID',
  'Name',
  'Description',
  color: Color.fromARGB(255, 0, 0, 0),
  importance: Importance.max,
  sound: RawResourceAndroidNotificationSound('notification_sound'),
  playSound: true,
  priority: Priority.high,
  showWhen: false,
);

const iOSPlatformChannel = IOSNotificationDetails(
  sound: 'notification_sound.aiff',
  presentAlert: true,
  presentBadge: true,
  presentSound: true,
);

const platformChannel = NotificationDetails(
  android: androidPlatformChannel,
  iOS: iOSPlatformChannel,
);

Then show a notification:

await flutterLocalNotificationsPlugin.show(
      id,
      title,
      body,
      platformChannel,
      payload: notification.payload,
    );

IMPORTANT! notification_sound.aiff file should be copied with XCode

Upvotes: 1

Abdelouahed Medjoudja
Abdelouahed Medjoudja

Reputation: 19

Use flutter_local_notifications package

AndroidNotificationDetails androidNotificationsDetails = AndroidNotificationDetails(
       'your other channel id',
       'your other channel name',
       'your other channel description',
        importance: Importance.Max,
        priority: Priority.Max,
        enableLights: true,
        playSound: true,
        sound: RawResourceAndroidNotificationSound('notification'),
);

Note: you should add notification.mp3 file in android/app/src/main/res/raw/notification.mp3 and don't forget to specify playSound:

playSound: true,

this worked for me in the foreground / background and when the app is closed.

Upvotes: 1

Mohi Dev
Mohi Dev

Reputation: 3376

You must create notification channel first with following code

Application.kt

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;

import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
import io.flutter.plugins.pathprovider.PathProviderPlugin;

import io.flutter.plugin.common.MethodChannel
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.net.Uri;
import android.media.AudioAttributes;
import android.content.ContentResolver;

class Application : FlutterApplication(), PluginRegistrantCallback {
    override fun onCreate() {
        super.onCreate()
        this.createChannel()
        FlutterFirebaseMessagingService.setPluginRegistrant(this)
    }

    override fun registerWith(registry: PluginRegistry?) {
//        createChannel();
        FirebaseCloudMessagingPluginRegistrant.registerWith(registry);
    }

    private fun createChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Create the NotificationChannel
            val name: String = getString(R.string.default_notification_channel_id)
            val channel = NotificationChannel(name, "default", NotificationManager.IMPORTANCE_HIGH)
            val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"+ getApplicationContext().getPackageName() + "/raw/sample");
            val att = AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                    .build();
            channel.setSound(soundUri, att)

            val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)

            /*
            val id = mapData["id"]
            val name = mapData["name"]
            val descriptionText = mapData["description"]
            val sound = "sample"
            val importance = NotificationManager.IMPORTANCE_HIGH
            val mChannel = NotificationChannel(id, name, importance)
            mChannel.description = descriptionText





            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(mChannel)
            completed = true
             */
        }
    }
}

And android manifest.xml

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.foodlz.orders">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.VIBRATE" />

    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
         calls FlutterMain.startInitialization(this); in its onCreate method.
         In most cases you can leave this as-is, but you if you want to provide
         additional functionality it is fine to subclass or reimplement
         FlutterApplication and put your custom class here. -->
    <application
        android:name=".Application"
        android:label="test App"
        android:icon="@mipmap/ic_launcher">




        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- This keeps the window background of the activity showing
                 until Flutter renders its first frame. It can be removed if
                 there is no splash screen (such as the default splash screen
                 defined in @style/LaunchTheme). -->
            <meta-data
                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
                android:value="true" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="@string/default_notification_channel_id"/>


        <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_appstore" />

        <meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/colorPrimary" />
    </application>


</manifest>


finally you must put your notification sound.wav file in res/raw

that's it

Upvotes: 0

fpsColton
fpsColton

Reputation: 873

To create a custom notification sound for both Android you will need to predefine a Notification Channel for your app. I used Flutter Local Notifications plugin to do this. In there, you can specify the parameters for your Android Notification Channel such as

var androidPlatformChannelSpecifics = AndroidNotificationDetails( 'your other channel id', 'your other channel name', 'your other channel description', sound: RawResourceAndroidNotificationSound('slow_spring_board');

Note: slow_spring_board.mp3 is stored in the android\app\src\main\res\raw section of your app. Do not include the file extension when calling RawResourceAndroidNotificationSound()

There are other steps required to get it setup for iOS devices (mp3 are not supported). Once this is all done, you can begin working on your cloud messaging portion, in there you'll have to reference the notification channel id, and the sound file. I recommend including the audio file extension in that code.

Upvotes: 0

Oto-obong Eshiett
Oto-obong Eshiett

Reputation: 1679

you can do this simply by calling the sound and playing it in the firebase configure method.

widget._firebaseMessaging.configure(
  onMessage: (Map<String, dynamic> message) async {
    print('on message $message');



    AudioCache player = new AudioCache();
    const alarmAudioPath = "sounds/notification.mp3";
    player.play(alarmAudioPath);
  },
  onResume: (Map<String, dynamic> message) async {
    print('on resume $message');
  },
  onLaunch: (Map<String, dynamic> message) async {
    print('on launch $message');
  },
);

this wouldnt be effective as the file wouldnt be played if the app is in the background

Upvotes: 0

Related Questions