我目前正在使用Firebase消息云推送通知我的应用程序。我正在尝试为推送通知制作自定义通知音。我相信可以通过在有效载荷中放置“sound:blabla.mp3”来实现,但是我该如何在Dart页面内定义声音?
这可以通过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时进行复制。
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'),
);
playSound: true,
要为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和声音文件。我建议在该代码中包含音频文件扩展名。
你可以通过在 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');
},
);
如果应用程序在后台运行,这种方法将不会有效,因为文件不会被播放。
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