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

Flutter后台与终止状态下Firebase推送通知API回调实现求助

解决方案:Firebase推送后台/终止状态下发送回执API

一、修复Firebase onBackgroundHandler的API调用问题

onBackgroundHandler运行在隔离的后台Isolate中,默认HTTP客户端常因缺少平台配置、初始化不全导致调用失败,按以下步骤修正:

  1. 补充Android后台网络权限
    在AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Android 12+ 后台推送与网络权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  1. 使用适配后台Isolate的HTTP客户端
    避免用默认http包,改用dio并配置超时、证书信任(自签证书场景):
Future<void> _sendReceipt(String notificationId) async {
  try {
    Dio dio = Dio();
    await dio.post(
      'https://your-server-url/api/receipt',
      data: {'notification_id': notificationId, 'status': 'received'},
      options: Options(
        sendTimeout: const Duration(seconds: 10),
        receiveTimeout: const Duration(seconds: 10),
      ),
    );
  } catch (e) {
    print('发送回执失败: $e');
    // 可添加本地存储,后续重试逻辑
  }
}
  1. 规范配置后台消息处理器
    确保handler为顶级函数,且在Isolate内初始化Firebase核心:
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  String? notificationId = message.data['notification_id'];
  if (notificationId != null) {
    await _sendReceipt(notificationId);
  }
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
  runApp(const MyApp());
}

二、WorkManager终止状态不工作的修复(Android为主)

WorkManager在App完全终止时依赖系统JobScheduler,需调整配置适配:

  1. 修改AndroidManifest禁用默认初始化
    避免系统延迟调度任务:
<provider
  android:name="androidx.startup.InitializationProvider"
  android:authorities="${applicationId}.androidx-startup"
  android:exported="false"
  tools:node="merge">
  <meta-data
    android:name="androidx.work.WorkManagerInitializer"
    android:value="androidx.startup"
    tools:node="remove" />
</provider>

<service
  android:name="androidx.work.impl.background.systemalarm.SystemAlarmService"
  android:permission="android.permission.BIND_JOB_SERVICE"
  android:exported="false" />
  1. 使用即时一次性任务触发回执
    在推送到达时触发WorkManager,强制立即执行:
void scheduleReceiptWork(String notificationId) {
  Workmanager().registerOneTimeTask(
    'receipt_${notificationId}',
    'send_receipt_task',
    inputData: {'notification_id': notificationId},
    constraints: Constraints(
      networkType: NetworkType.connected,
    ),
    initialDelay: Duration.zero,
  );
}

// 绑定到Firebase后台消息处理器
FirebaseMessaging.onBackgroundMessage((message) async {
  await Firebase.initializeApp();
  String? notificationId = message.data['notification_id'];
  if (notificationId != null) {
    scheduleReceiptWork(notificationId);
  }
});

// WorkManager任务调度器
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    String? notificationId = inputData?['notification_id'];
    if (notificationId != null) {
      await _sendReceipt(notificationId);
      return Future.value(true);
    }
    return Future.value(false);
  });
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await Workmanager().initialize(
    callbackDispatcher,
    isInDebugMode: false,
  );
  FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
  runApp(const MyApp());
}
  1. Android 12+ 前台服务适配
    避免任务被系统杀死,执行时启动低优先级前台通知:
// 在_sendReceipt中添加Android平台代码
if (Platform.isAndroid) {
  const AndroidNotificationDetails details = AndroidNotificationDetails(
    'receipt_service',
    '回执服务',
    importance: Importance.low,
    priority: Priority.low,
  );
  await FlutterLocalNotificationsPlugin().show(
    0,
    '处理通知回执',
    '正在发送确认信息',
    NotificationDetails(android: details),
  );
}

三、iOS平台特殊处理

iOS终止状态下仅支持静默推送,需满足以下条件:

  1. 开启后台推送权限
    在Info.plist中添加:
<key>UIBackgroundModes</key>
<array>
  <string>remote-notification</string>
</array>
  1. 推送Payload必须包含静默标识
    确保aps字段包含content-available: 1,且不要带alert字段:
{
  "aps": {
    "content-available": 1
  },
  "data": {
    "notification_id": "12345"
  }
}
  1. 原生代码处理静默推送
    在AppDelegate.swift中添加回执逻辑:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  if let notificationId = userInfo["notification_id"] as? String {
    let url = URL(string: "https://your-server-url/api/receipt")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = try? JSONSerialization.data(withJSONObject: ["notification_id": notificationId])
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    URLSession.shared.dataTask(with: request) { _, _, error in
      completionHandler(error != nil ? .failed : .newData)
    }.resume()
  } else {
    completionHandler(.noData)
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 07:18:19