You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter应用后台或关闭状态下FCM自定义通知声音无法播放的解决方案咨询

解决Flutter FCM后台/关闭状态下自定义通知声音不生效问题

我来帮你搞定这个问题!其实这是因为FCM在应用不同状态下的通知处理机制不一样,前台时你的代码能接管逻辑,但后台或完全关闭时是系统直接处理通知,咱们一步步调整就能解决:

1. 先搞懂FCM的两种消息类型

FCM消息分两种,这是关键:

  • 通知消息:带notification字段的消息,后台/关闭状态下是系统直接弹出通知,不会触发你代码里的onMessage回调
  • 数据消息:只有data字段的消息,任何状态下都会传给你的代码处理,但需要自己构建通知

你现在用的是带notification的消息,所以后台时系统接管了通知,自定义声音得让系统来播放,而不是靠你代码里的assetsAudioPlayer。

2. 修改FCM推送Payload

在notification字段里添加sound参数,指定你的自定义声音文件名:

{
  "notification": {
    "body": "this is a body",
    "title": "this is a title",
    "sound": "alert.mp3" // 这里填你的自定义声音文件名
  },
  "data": {
    "click_action":"FLUTTER_NOTIFICATION_CLICK",
    "type": "normal",
    "id": "1",
    "ride_id": "-MKp1WBP8G2kTgJBqwyl",
    "status": "done"
  },
  "to":"dv9Yq4qHSVubIohoM8niDX:APA91bGJgQkP7Ir867vyo9oT1CeXbWPKP6xMSDUgwu3242W9odgr4vn5qIIgPmY2LQyPNjL8Pwl8GcRY4TbucxVcCBOM0eBZDHnfhh0E0qYvhdWc_0Yd1oBT_Vh1sA0q-haqXQ3KXib5"
}

3. 客户端配置(Android + iOS)

Android端

  • 把你的alert.mp3文件复制到android/app/src/main/res/raw/目录(没有raw文件夹就新建一个)
  • 文件名必须符合Android资源规则:只能用小写字母、数字、下划线,不能有空格或特殊字符
  • 确保AndroidManifest.xml里有必要权限:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.VIBRATE" />
    

iOS端

  • 把音频文件添加到Xcode项目中,勾选「Copy items if needed」和对应的target
  • 在Info.plist里添加配置,开启远程通知后台模式:
    <key>UIBackgroundModes</key>
    <array>
      <string>remote-notification</string>
    </array>
    <key>UNNotificationSoundName</key>
    <string>alert.mp3</string>
    
  • 确保在Xcode的「Signing & Capabilities」里开启了「Background Modes」并勾选「Remote notifications」

4. 调整Flutter代码逻辑

前台时你可以继续用assetsAudioPlayer播放声音,但后台/关闭状态下系统已经播放过了,不需要重复触发。另外建议升级到新版FCM API(你用的configure是旧版):

class PushNotificationService{
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
  
  Future initialize(BuildContext context) async{
    // 请求通知权限(必须开启sound权限)
    NotificationSettings settings = await _firebaseMessaging.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );

    // 前台收到消息时的处理
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      print("onMessage: ${message.toMap()}");
      fetchRideInfo(message.data['orderId'], context);
    });

    // 点击通知启动应用(关闭状态)
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      print("onMessageOpenedApp: ${message.toMap()}");
      fetchRideInfo(message.data['orderId'], context);
    });
  }

  Future<String> getToken() async{
    print("fetching token");
    String? token = await _firebaseMessaging.getToken();
    print('token got as: $token');
    return token ?? '';
  }

  void fetchRideInfo(String? orderId, BuildContext context) {
    if (orderId == null) return;
    print("fetching info for order: $orderId");
    
    showDialog(
      barrierDismissible: false,
      context: context,
      builder: (BuildContext context) => CustomProgressDialog(status:'Fetching details',),
    );

    // 只有前台时播放自定义声音,后台/启动时系统已经处理过了
    if (_firebaseMessaging.app.isForeground) {
      assetsAudioPlayer.open(Audio('sounds/alert.mp3'));
      assetsAudioPlayer.play();
    }
  }
}

5. 常见排查点

  • 确认音频文件格式:Android支持mp3/wav,iOS支持caf/mp3
  • 检查文件名是否符合平台要求,Android不能有大写字母
  • 测试时不要用模拟器,尽量用真机测试(模拟器可能有通知声音限制)

内容的提问来源于stack exchange,提问作者custom apps

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 06:43:12