You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Invertase实现React Native iOS设备FCM推送失败排查

解决iOS端Invertase FCM推送无响应的问题

首先明确:你完全不需要依赖zo0r/react-native-push-notificationwix/react-native-notifications这类第三方库,Invertase的@react-native-firebase/messaging本身就足够处理iOS的推送通知,那些库只是用来扩展本地通知的管理能力,基础的FCM推送完全可以靠官方库实现。

你能获取到token但收不到通知,大概率是iOS端的配置或代码逻辑有遗漏,下面一步步排查:

一、必须补全的iOS配置项

这些是iOS推送的基础门槛,缺一不可:

1. Xcode项目配置

  • 打开你的iOS项目,在Signing & Capabilities标签下,添加Push Notifications能力(确保自动生成的配置正确)
  • 同时添加Background Modes能力,勾选Remote notifications(后台接收推送需要)
  • 确认你的App ID在苹果开发者后台已经启用了Push Notifications服务

2. Firebase控制台配置

  • 进入Firebase项目设置 → Cloud Messaging标签,找到iOS应用的配置区域
  • 上传对应的APNs证书(开发/生产环境要区分),或者使用Token验证(推荐,更灵活):
    • 从苹果开发者后台生成APNs Auth Key,上传到Firebase
    • 填写对应的Team ID和Key ID

3. iOS系统权限细节

  • iOS 10+需要用户明确授权通知权限,requestPermission要包含必要的选项:
    await messaging().requestPermission({
      alert: true,
      badge: true,
      sound: true,
    });
    
  • 光请求权限还不够,必须调用系统API注册远程通知:
    // 请求权限后,调用这个方法触发系统注册
    await messaging().registerDeviceForRemoteNotifications();
    

二、代码端的必要逻辑处理

除了获取token,你还需要处理不同状态下的通知接收:

1. 完整的初始化代码示例

import messaging from '@react-native-firebase/messaging';
import { Platform } from 'react-native';

// 应用启动时初始化推送
const setupFCM = async () => {
  // 1. 请求权限
  const authStatus = await messaging().requestPermission({
    alert: true,
    badge: true,
    sound: true,
  });
  const enabled =
    authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
    authStatus === messaging.AuthorizationStatus.PROVISIONAL;

  if (enabled) {
    // 2. 注册远程通知(iOS必须)
    if (Platform.OS === 'ios') {
      await messaging().registerDeviceForRemoteNotifications();
    }

    // 3. 获取token
    const token = await messaging().getToken();
    console.log('FCM Token:', token);

    // 4. 监听前台通知接收
    messaging().onMessage(async remoteMessage => {
      console.log('前台收到通知:', remoteMessage);
      // 如果需要在前台显示通知,iOS需要手动创建本地通知(默认前台不弹窗)
      // 可以用@react-native-firebase/notifications库来创建,或者原生代码
    });

    // 5. 监听后台通知点击
    messaging().onNotificationOpenedApp(remoteMessage => {
      console.log('后台点击通知:', remoteMessage);
      // 处理跳转逻辑
    });

    // 6. 监听应用杀死状态下的通知点击
    const initialNotification = await messaging().getInitialNotification();
    if (initialNotification) {
      console.log('杀死状态点击通知:', initialNotification);
    }
  }
};

// 在App组件的useEffect里调用
useEffect(() => {
  setupFCM();
}, []);

2. iOS原生层(AppDelegate)配置

如果是React Native 0.60+,react-native-firebase会自动配置,但如果有问题,手动检查AppDelegate.m

#import <Firebase.h>
#import <UserNotifications/UserNotifications.h>
#import <RNFBApp/RNFBAppModule.h>
#import <RNFBMessaging/RNFBMessagingModule.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  // 配置UNUserNotificationCenter代理
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;
  
  // ...其他原有代码
  return YES;
}

// iOS 10+:前台接收通知时的回调
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
{
  completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}

// iOS 10+:通知点击回调
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler
{
  [RNFBMessagingModule didReceiveNotificationResponse:response];
  completionHandler();
}

// 处理APNs token注册
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
  [RNFBMessagingModule didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
  [RNFBMessagingModule didFailToRegisterForRemoteNotificationsWithError:error];
}

@end

三、推送Payload的格式要求

iOS对FCM的payload有严格要求,必须包含aps字段,否则系统不会触发通知。示例正确的payload:

// Firebase Admin SDK发送示例
const message = {
  token: 'DEVICE_TOKEN',
  notification: {
    title: '测试通知',
    body: '这是iOS测试推送',
  },
  apns: {
    payload: {
      aps: {
        alert: {
          title: '测试通知',
          body: '这是iOS测试推送',
        },
        badge: 1,
        sound: 'default',
      },
    },
  },
};

await admin.messaging().send(message);

注意:如果只发notification字段,FCM会自动转换为aps格式,但如果是data消息,iOS后台/杀死状态下不会自动弹窗,需要你在代码里手动处理。

最后排查点

  • 确认测试设备的iOS版本,iOS 14+需要用户允许通知(设置→你的App→通知)
  • 区分开发环境和生产环境:开发用APNs开发证书,生产用生产证书,Firebase控制台要对应配置
  • 检查Firebase Admin SDK的版本,确保和客户端库版本兼容

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

火山引擎 最新活动