Flutter中针对FCM的自定义通知渠道

5

我试图自定义Flutter中firebase_messaging的通知声音。在前台,我正在使用flutter_local_notifications包来实现通知,其中我设置了自定义声音和振动。但是,在后台,通知由默认通知渠道处理。是否有任何方法可以创建通知渠道或使用我刚刚使用flutter_local_notifications包创建的通知渠道?

4个回答

3

如果您在应用程序处于后台时希望收到“悬浮通知”并且想要自定义声音,那么您可能需要创建一个通知渠道。 FCM使用的默认通知渠道未启用“弹出屏幕”设置,并使用默认系统声音。您可以通过在设备上打开应用程序的设置来查看此设置。

OP正在使用flutter_local_notifications包,这几乎是Flutter中处理通知的“首选”包。您可以通过createNotificationChannel方法创建自己的通知渠道,并分配所需的参数(包括声音和优先级)。这是让您的通知按照您的意愿进行操作的快速简便的方法。

如果您想在不使用flutter_local_notifications包的情况下创建自己的通知渠道,则必须以其本机形式修改MainActivity.kt(或Java)文件。这并不是太复杂,但比仅使用flutter_local_notifications包更低级别。 此Medium文章描述了如何执行此操作(适用于Android)。


1
有关iOS的任何想法? - Shalabyer
1
@Shalabyer 这个问答应该会对你有所帮助——这就是我设置我的方式:https://dev59.com/QlQJ5IYBdhLWcg3wYEu7#63922550 - Sludge
谢谢您的回复,我一定会尝试的。 - Shalabyer
我刚刚查看了那个问答,我认为它只能在前台工作,因为在回答中他没有创建通知通道,而我们需要通知通道来使自定义声音在后台播放,我的理解是正确的吗? - Shalabyer
1
@Shalabyer 在iOS上,你不像在Android上那样创建通知渠道--你是否按照那个Q/A中的说明将资产添加到你的捆绑包中?你可能需要调整你的JSON有效负载,我也曾经试错了一些次才得到它,不幸的是我现在没有它在我面前给你。也许这个Q/A会指导你?https://dev59.com/rlgR5IYBdhLWcg3wO7Q0 - Sludge
谢谢,我一定会尝试的,这些提供的信息非常有帮助 :) - Shalabyer

2
在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中,它对于直接使用声音文件是必要的。


0

如果您在 Firebase 控制台中发送通知时,可以在“其他选项”中指定频道 ID,在那里您可以编写使用 flutter_local_notifications 已创建的频道。

希望这可以帮助到您!


0

由于您已经在使用flutter_local_notifications,因此有一种替代方法可以实现@Elmar提到的Android实现方式。

根据FCM Legacy API Doc

通知的频道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

URLhttps://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" 
    }
}

注:声音是可选的,如果您有多个自定义声音,请在频道中启用播放声音并在通知有效载荷中包含自定义声音的文件名。


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