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

Flutter应用杀死重启后FCM Token变更,导致推送消息无法接收如何解决

Flutter FCM Token重启应用后变更的原因及解决办法

可能的原因

  • 签名/证书不一致:调试和正式环境用了不同签名证书,或者证书更新过,FCM会判定为不同应用实例,重启后生成新Token。
  • 存储权限缺失:FCM需要将Token持久化到设备本地,若应用未获取存储权限,重启后无法读取旧Token,只能重新生成。
  • SDK版本bug:部分旧版firebase_messaging SDK存在重启后重复生成Token的问题,Android平台尤为明显。
  • 应用数据被清理:系统或第三方清理工具在应用杀死后清理了缓存/数据,FCM存储的Token丢失,重启后需重新生成。
  • Android 13+通知权限问题:Android 13及以上需单独申请POST_NOTIFICATIONS权限,未授予时可能导致FCM重启后刷新Token。

解决办法

  • 统一签名配置:确保调试、正式环境使用相同签名证书,在android/app/build.gradle中固定签名信息,避免环境差异引发Token变更。
  • 申请存储权限:在AndroidManifest.xml中添加存储权限(旧版Android需READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE),并在应用启动时主动申请,保证FCM能持久化Token。
  • 更新Firebase SDK:将firebase_messaging等依赖升级到最新稳定版,修复已知的Token重复生成bug。
  • 手动持久化Token:获取到Token后,存入SharedPreferences或Hive等本地存储,重启时优先读取本地Token,不存在再调用getToken()。示例代码:
import 'package:shared_preferences/shared_preferences.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

Future<String?> getFCMToken() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  String? savedToken = prefs.getString('fcm_token');
  if (savedToken != null) {
    return savedToken;
  }
  String? newToken = await FirebaseMessaging.instance.getToken();
  if (newToken != null) {
    await prefs.setString('fcm_token', newToken);
  }
  return newToken;
}
  • 监听Token刷新事件:通过onTokenRefresh监听Token变更,及时同步到后端服务器,并更新本地存储。示例代码:
import 'package:shared_preferences/shared_preferences.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

FirebaseMessaging.instance.onTokenRefresh.listen((newToken) async {
  // 同步新Token到后端
  updateTokenOnServer(newToken);
  // 更新本地存储
  SharedPreferences prefs = await SharedPreferences.getInstance();
  await prefs.setString('fcm_token', newToken);
});

// 自行实现后端同步逻辑
void updateTokenOnServer(String token) {
  // 你的API请求代码
}
  • 申请Android 13+通知权限:在AndroidManifest.xml添加POST_NOTIFICATIONS权限,启动时主动请求权限。示例代码:
import 'package:permission_handler/permission_handler.dart';

Future<void> requestNotificationPermission() async {
  if (await Permission.notification.isDenied) {
    await Permission.notification.request();
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 09:56:03