我试图自定义Flutter中firebase_messaging的通知声音。在前台,我正在使用flutter_local_notifications包来实现通知,其中我设置了自定义声音和振动。但是,在后台,通知由默认通知渠道处理。是否有任何方法可以创建通知渠道或使用我刚刚使用flutter_local_notifications包创建的通知渠道?
我试图自定义Flutter中firebase_messaging的通知声音。在前台,我正在使用flutter_local_notifications包来实现通知,其中我设置了自定义声音和振动。但是,在后台,通知由默认通知渠道处理。是否有任何方法可以创建通知渠道或使用我刚刚使用flutter_local_notifications包创建的通知渠道?
如果您在应用程序处于后台时希望收到“悬浮通知”并且想要自定义声音,那么您可能需要创建一个通知渠道。 FCM使用的默认通知渠道未启用“弹出屏幕”设置,并使用默认系统声音。您可以通过在设备上打开应用程序的设置来查看此设置。
OP正在使用flutter_local_notifications包,这几乎是Flutter中处理通知的“首选”包。您可以通过createNotificationChannel
方法创建自己的通知渠道,并分配所需的参数(包括声音和优先级)。这是让您的通知按照您的意愿进行操作的快速简便的方法。
如果您想在不使用flutter_local_notifications包的情况下创建自己的通知渠道,则必须以其本机形式修改MainActivity.kt
(或Java)文件。这并不是太复杂,但比仅使用flutter_local_notifications包更低级别。 此Medium文章描述了如何执行此操作(适用于Android)。
package com.example.new_channel //Your own package name
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.content.Context
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.app.NotificationManager;
import android.app.NotificationChannel;
import android.net.Uri;
import android.media.AudioAttributes;
import android.content.ContentResolver;
class MainActivity: FlutterActivity() {
private val CHANNEL = "somethinguniqueforyou.com/channel_test" //The channel name you set in your main.dart file
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// Note: this method is invoked on the main thread.
call, result ->
if (call.method == "createNotificationChannel"){
val argData = call.arguments as java.util.HashMap<String, String>
val completed = createNotificationChannel(argData)
if (completed == true){
result.success(completed)
}
else{
result.error("Error Code", "Error Message", null)
}
} else {
result.notImplemented()
}
}
}
private fun createNotificationChannel(mapData: HashMap<String,String>): Boolean {
val completed: Boolean
if (VERSION.SDK_INT >= VERSION_CODES.O) {
// Create the NotificationChannel
val id = mapData["id"]
val name = mapData["name"]
val descriptionText = mapData["description"]
val sound = "your_sweet_sound"
val importance = NotificationManager.IMPORTANCE_HIGH
val mChannel = NotificationChannel(id, name, importance)
mChannel.description = descriptionText
val soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"+ getApplicationContext().getPackageName() + "/raw/your_sweet_sound");
val att = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.build();
mChannel.setSound(soundUri, att)
// 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
}
else{
completed = false
}
return completed
}
}
点击此处查看。
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import android.media.AudioAttributes;
import androidx.core.app.NotificationCompat;
import android.net.Uri;
import android.content.ContentResolver;
this is a code
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(“new_email_arrived_channel”, “My Emailer”, NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setShowBadge(true);
notificationChannel.setDescription(“”);
AudioAttributes att = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
.build();
notificationChannel.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + “://” + getPackageName() + “/raw/bell”), att);
notificationChannel.enableVibration(true);
notificationChannel.setVibrationPattern(new long[]{400, 400});
notificationChannel.setLockscreenVisibility(NotificationCompat.VISIBILITY_PUBLIC);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(notificationChannel);
}
String _statusText = "Waiting...";
final String _finished = "Finished creating channel";
final String _error = "Error while creating channel";
static const MethodChannel _channel =
MethodChannel('somethinguniqueforyou.com/channel_test');
Map<String, String> channelMap = {
"id": "CHAT_MESSAGES",
"name": "Chats",
"description": "Chat notifications",
};
void _createNewChannel() async {
try {
await _channel.invokeMethod('createNotificationChannel', channelMap);
setState(() {
_statusText = _finished;
});
} on PlatformException catch (e) {
_statusText = _error;
print(e);
}
}
"notification": {
"body": "Test notification",
"title": "Test Test Test",
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"sound": "your_custom_sound"
"android_channel_id": "channel_id_youcreated",
},
'to':
"",
},
如果您通过MainActivity.kt或Java文件为通知通道分配了声音,则在上述通知负载中,声音文件名并不是必需的。但是,在旧版Android中,它对于直接使用声音文件是必要的。
如果您在 Firebase 控制台中发送通知时,可以在“其他选项”中指定频道 ID,在那里您可以编写使用 flutter_local_notifications 已创建的频道。
希望这可以帮助到您!
由于您已经在使用flutter_local_notifications
,因此有一种替代方法可以实现@Elmar提到的Android实现方式。
通知的频道ID(Android O中的新功能)。
应用程序必须在接收到具有此频道ID的任何通知之前创建具有此频道ID的频道。
如果您没有在请求中发送此频道ID,或者提供的频道ID尚未被应用程序创建,则FCM将使用应用程序清单中指定的频道ID。
步骤1:定义Android通知渠道
/// The plugin
FlutterLocalNotificationsPlugin? flutterLocalNotificationsPlugin;
/// File name should not have the extension
static const String soundFileName = 'file_name_of_sound';
/// Custom notification channel
final channel = const AndroidNotificationChannel(
'custom_notification_channel_01',
'Notification channel with custom sound notifications',
description: 'This channel is used for notifications with a custom sound.',
importance: Importance.high,
playSound: true,
sound: RawResourceAndroidNotificationSound(soundFileName),
);
步骤2:创建通知渠道,应该在代码早期完成,最好是在初始化FirebaseMessaging
的地方。
await flutterLocalNotificationsPlugin
?.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
步骤三:在后端推送通知中包含 Android 渠道 ID。
现在您可以开始测试此功能,使用 Postman 或您选择的客户端进行本地测试。
方法:POST
URL:https://fcm.googleapis.com/fcm/send
头部:不要忘记添加 Authorization=key=${server_key_from_firebase_console}
正文:
{
"to": "fcm_token",
"notification": {
"android_channel_id": "custom_notification_channel_01",
"title": "Title of the custom notification",
"body": "An important notification with a custom sound",
"sound": "custom_sound_file_name"
}
}
注:声音是可选的,如果您有多个自定义声音,请在频道中启用播放声音并在通知有效载荷中包含自定义声音的文件名。