我正在尝试自定义颤振中firebase_messaging的通知声音。在前台,我正在实现flutter_local_notifications包来传递通知,其中我设置了自定义声音和振动。但在后台的情况下,通知由默认通知通道处理。有什么方法可以创建通知通道或使用我刚刚使用包创建的通知通道flutter_local_notifications?
对于那些因为您的 FCM 消息在后台运行时没有按照您喜欢的方式运行而来到这里的人:
如果您希望在应用在后台运行时发出"提醒"通知,并且您希望拥有自己的自定义声音,则可能需要创建通知通道。FCM 使用的默认通知通道未启用"弹出屏幕"设置,而是使用默认系统声音。您可以通过转到设备上的应用程序设置来查看此信息。
OP 正在使用 flutter_local_notifications 包,它几乎是 flutter 中通知处理的"首选"包。您可以通过createNotificationChannel
方法创建自己的通知通道,并分配所需的参数(包括声音和优先级(。这是让通知按照您想要的方式运行的快速简便的方法。
如果要在没有flutter_local_notifications包的情况下创建自己的通知通道,则必须以本机形式修改MainActivity.kt
(或 Java(文件。它并不太复杂,但它比仅使用 flutter_local_notifications 包更底层。这篇Medium帖子描述了如何做到这一点(对于Android(。
在 Flutter 中,您可以通过 MainActivity.kt 或 MainActivity.java 文件自行创建 android 通知通道,具体取决于项目 Android 文件夹中的任何一个。这里的好指南 - 使用简单且有效的 MainActivity.kt,我自己尝试过 - 它有效:
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
}
}
这是MainActivity java:
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);
}
在 Flutter 端,您可能需要触发器来启动进程并命名通知通道。它来自上面的同一来源:
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);
}
}
现在,对于所有Android版本,您只需要以下格式的通知有效负载:
"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 for Android。
根据 FCM 旧版 API 文档
通知的频道 ID(Android O 中的新增功能(。
应用必须先创建具有此频道 ID 的频道,然后才能创建任何频道 收到具有此通道 ID 的通知。
如果您未在请求中发送此频道 ID,或者频道 ID 前提是应用尚未创建,FCM 使用频道 ID 在应用清单中指定。
第 1 步:定义安卓通知渠道
/// 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);
第 3 步:在后端的推送通知中包含安卓频道 ID。
现在你很好了,使用邮递员或你选择的客户在本地测试这个。
方法:发布
网址: 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"
}
}
PS:声音是可选的,如果您有多个自定义声音,请在频道中启用播放声音,并在通知有效负载中包含自定义声音的文件名。