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

Flutter中Awesome Notifications后台/终止状态下不显示问题排查

问题根源分析

你的核心问题是:客户端Firebase实时数据库监听仅在APP前台进程存活时有效,当APP进入后台或被终止时,进程被系统挂起/杀死,监听停止运行,无法触发通知生成逻辑。重新打开APP时,监听重启,会一次性拉取之前所有未处理的数据库变更事件,导致通知批量弹出。

Awesome Notifications本身只是本地通知展示工具,它无法让你的APP在后台/终止状态下持续运行数据库监听——这是移动平台的进程限制导致的。

解决方案:改用FCM推送+本地通知展示

最可靠的方式是通过Firebase Cloud Messaging(FCM) 实现跨状态通知,由服务器端(而非客户端)监听数据库变更并触发推送,系统级推送服务能确保APP在后台/终止状态下也能收到通知。

步骤1:集成FCM并获取设备令牌

  1. 在pubspec.yaml添加依赖:
dependencies:
  firebase_core: ^2.15.0
  firebase_messaging: ^14.6.5
  awesome_notifications: ^0.7.4
  1. 在main.dart初始化FCM并保存设备令牌到Firebase数据库(关联用户ID):
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  // 初始化Awesome Notifications通道
  await AwesomeNotifications().initialize(
    null,
    [
      NotificationChannel(
        channelKey: 'basic_channel',
        channelName: '订单通知',
        channelDescription: '订单状态更新通知',
        defaultColor: Colors.orange,
        importance: NotificationImportance.High,
        channelShowBadge: true,
      )
    ]
  );

  // 请求通知权限
  await AwesomeNotifications().isNotificationAllowed().then((isAllowed) {
    if (!isAllowed) {
      AwesomeNotifications().requestPermissionToSendNotifications();
    }
  });

  // 获取并保存FCM令牌到用户数据中
  String? fcmToken = await FirebaseMessaging.instance.getToken();
  if (fcmToken != null && loggedInUserID != null) {
    await FirebaseDatabase.instance.ref('Users/$loggedInUserID/fcmToken').set(fcmToken);
  }

  runApp(const MyApp());
}

步骤2:编写Firebase Functions触发器(服务器端)

创建Firebase Functions,监听数据库订单状态变更,向对应用户发送FCM推送:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

// 监听订单接受/拒绝事件
exports.sendOrderStatusNotification = functions.database.ref('/ManagedOrders/{orderId}')
    .onCreate(async (snapshot, context) => {
        const orderData = snapshot.val();
        const customerID = orderData.customerID;
        const orderNum = orderData.orderNum;
        const status = orderData.status;

        // 获取用户的FCM令牌
        const userSnapshot = await admin.database().ref(`/Users/${customerID}/fcmToken`).once('value');
        const fcmToken = userSnapshot.val();
        if (!fcmToken) return;

        let title, body;
        switch(status) {
            case 'accepted':
                title = "👍 你的订单(订单号:" + orderNum + ")已接受!";
                body = "Nandos正在准备你的餐品";
                break;
            case 'rejected':
                title = "👎 你的订单(订单号:" + orderNum + ")已被拒绝!";
                body = "Nandos目前无法处理你的订单";
                break;
            default:
                return;
        }

        // 发送FCM推送
        const message = {
            notification: {title, body},
            token: fcmToken,
            data: {orderNum, status}
        };
        await admin.messaging().send(message);
    });

// 监听订单完成事件
exports.sendCompletedOrderNotification = functions.database.ref('/CompleteOrders/{orderId}')
    .onCreate(async (snapshot, context) => {
        const orderData = snapshot.val();
        const customerID = orderData.customerID;
        const orderNum = orderData.orderNum;

        const userSnapshot = await admin.database().ref(`/Users/${customerID}/fcmToken`).once('value');
        const fcmToken = userSnapshot.val();
        if (!fcmToken) return;

        const title = "🎆 你的订单(订单号:" + orderNum + ")已准备好可取餐!";
        const body = "请前往Nandos取餐";

        const message = {
            notification: {title, body},
            token: fcmToken,
            data: {orderNum, status: 'completed'}
        };
        await admin.messaging().send(message);
    });

步骤3:客户端处理FCM消息并展示通知

在main.dart中添加FCM消息监听,用Awesome Notifications展示:

void main() async {
  // ... 前面的初始化代码 ...

  // 处理前台收到的FCM消息
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    if (message.notification != null) {
      AwesomeNotifications().createNotification(
        content: NotificationContent(
          id: DateTime.now().millisecondsSinceEpoch ~/ 1000,
          channelKey: 'basic_channel',
          title: message.notification!.title,
          body: message.notification!.body,
          payload: message.data,
        ),
      );
    }
  });

  // 处理点击通知打开APP的逻辑
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    // 这里可以跳转到订单详情页,示例:
    // Navigator.push(context, MaterialPageRoute(builder: (_) => OrderDetailPage(orderNum: message.data['orderNum'])));
  });

  runApp(const MyApp());
}

步骤4:移除客户端数据库监听

删除AuthenticationWrapper中的listenForAcceptedOrders、listenForRejectedOrders、listenForCompletedOrders调用,现在由服务器端触发器处理通知逻辑,无需客户端持续监听。

关键注意事项
  • iOS需配置APNs证书,确保推送能正常送达;
  • Android需关闭APP的电池优化限制,避免系统拦截后台推送;
  • Awesome Notifications的NotificationImportance需设为High,确保通知在后台能弹出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 09:25:21