使用自定义声音的Firebase推送通知(Flutter)

14

我目前正在使用Firebase消息云推送通知我的应用程序。我正在尝试为推送通知制作自定义通知音。我相信可以通过在有效载荷中放置“sound:blabla.mp3”来实现,但是我该如何在Dart页面内定义声音?

5个回答

1

这可以通过flutter_local_notifications插件实现。

首先,您需要为Android和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,
);

然后显示一个通知:
await flutterLocalNotificationsPlugin.show(
      id,
      title,
      body,
      platformChannel,
      payload: notification.payload,
    );

重要提示! notification_sound.aiff 文件应该在使用XCode时进行复制。


2
这是针对前台通知的,当应用程序被杀死时,它是否适用于后台? - Oleksandr Yefymov
1
它在后台没有工作。 - samad shukr

1
使用 flutter_local_notifications 包。
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'),
);

注意:您应该将 notification.mp3 文件添加到 android/app/src/main/res/raw/notification.mp3 中,并且不要忘记指定 playSound。
playSound: true,

这对我来说在前台/后台和应用程序关闭时都有效。

我还没有在IOS上尝试过。 - Abdelouahed Medjoudja
它不能与iOS一起使用。 - samad shukr
嗨,我有一个问题,我的声音无法播放,无论应用程序是打开还是在后台。 - MNFS

0

要为Android创建自定义通知声音,您需要预定义应用程序的Notification Channel。我使用 Flutter Local Notifications 插件来完成这项工作。在那里,您可以指定Android Notification Channel的参数,例如:

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

注意:slow_spring_board.mp3 存储在您的应用程序的 android\app\src\main\res\raw 部分中。调用 RawResourceAndroidNotificationSound() 时不要包括文件扩展名。

还有其他步骤需要为iOS设备设置(mp3不受支持)。完成所有步骤后,您可以开始处理云消息部分,在那里您将不得不引用通知渠道ID和声音文件。我建议在该代码中包含音频文件扩展名。


嗨@fpsColton,我也遇到了同样的问题。我已经在Flutter代码中创建了通道。但是自定义声音没有播放。您有什么建议吗?请看下面:\n const AndroidNotificationChannel channel = AndroidNotificationChannel( 'high_importance_channel', // id 'High Importance Notifications', // title 'This channel is used for important notifications.', // description importance: Importance.max, enableVibration: true, playSound: true, sound: RawResourceAndroidNotificationSound('lfid_emergency')); - Hiren
@Hiren,你应该尝试预先定义一个AndroidNotificationDetails对象(包括channelAction:AndroidNotificationChannelAction.CreateIfNotExists字段),然后将其传递给NotificationDetails对象,该对象用作flutterLocalNotificationsPlugin.show()函数的参数。 - fpsColton
那么iOS呢?有帮助吗? - Shalabyer
请问设置iOS设备还需要哪些其他步骤? - Shalabyer
1
将音频文件存储为 .wav 格式,将其添加到 Xcode 项目的顶部(我的位于 PROJECT_DIR/ios/alert.wav)。然后在发送通知时定位该声音文件。例如: apns:{ payload:{ aps:{ sound:'alert.wav' } } } - fpsColton
我已经尝试了上述所有方法,但仍无法在后台工作。 - samad shukr

0

你可以通过在 Firebase 配置方法中调用声音并播放它来轻松实现此操作。

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');
  },
);

如果应用程序在后台运行,这种方法将不会有效,因为文件不会被播放。


1
那就是问题所在,我想要通知声音变成自定义声音。 - ali
您可以简单地将自定义音频放置在应用程序的Android本机部分中来实现此操作。默认情况下,Firebase会调用它。此外,我认为您不需要在blabla.mp3中加入“.mp3”,让我为您查看文章。 - Oto-obong Eshiett
尝试使用此链接 https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#AndroidNotification。请查看声音选项。 - Oto-obong Eshiett
可能是API出了问题,因为在Nougat之后,声音无法正常工作,但还是感谢您提供的链接。 - ali
我之前一直在使用安卓奥利奥,但当我使用我的旧 Nexus 5 并运行安卓 M 时,它可以正常工作。 - ali

0
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

1
iOS有什么想法吗? - Nicks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接