React Native项目中iOS设备未能接收到通知

3
我有一个React Native项目。我能够成功接收到FCM令牌,但在尝试发送通知时,应用程序无法接收通知。
我遵循的步骤如下:
  1. 在Firebase控制台中创建一个项目。
  2. 通过Xcode将Firebase .plist添加到projectName。
  3. 运行 npm install --save react-native-firebase
  4. 在podfile中添加:pod ‘Firebase/Core’
  5. 运行 pod install
  6. 使用 #import <Firebase.h>[FIRApp configure]; 更新AppDelegate.m
  7. 在Firebase仪表板中为iOS App Cloud Messaging添加APNS。
  8. 使用推送通知后台模式 > 远程通知更新功能。
  9. 在info.plist中,设置FIRAnalyticsDebugEnabledFirebaseAppDelegateProxyEnabledFirebaseScreenReportingEnabledNo
使用const fcmToken = await firebase.messaging().getToken();,我可以获得令牌。 下面是通知监听器的代码。
async createNotificationListeners() {

    /*

     * Triggered when a particular notification has been received in foreground

     * */



    this.notificationListener = firebase.notifications().onNotification((notification) => {


        const {
            title,
            body
        } = notification;

        this.custom_data = notification.data;

        const localNotification = new firebase.notifications.Notification({

                show_in_foreground: true,

            })

            .setSound('default')

            .setNotificationId(notification.notificationId)

            .setTitle(notification.title)

            .setBody(notification.body)




        firebase.notifications()

            .displayNotification(localNotification)

            .catch(err => Alert.alert(err));

    });




    /*

     * If your app is in foreground and background, you can listen for when a notification is clicked / tapped / opened as follows:

     * */

    this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {

        if ("title" in notificationOpen.notification.data) {

            const {
                title,
                body,
                secret_key,
                user_id,
                realm_id,
                user_os,
                user_location
            } = notificationOpen.notification.data;

            this.props.navigation.navigate('Verify', {
                title: title,
                body: body,

                secret_key: secret_key,
                user_id: user_id,
                realm_id: realm_id,
                user_os: user_os,
                user_location: user_location
            });

        } else {

            const {
                title,
                body,
                secret_key,
                user_id,
                realm_id,
                user_os,
                user_location
            } = this.custom_data;

            this.props.navigation.navigate('Verify', {
                title: title,
                body: body,

                secret_key: secret_key,
                user_id: user_id,
                realm_id: realm_id,
                user_os: user_os,
                user_location: user_location
            });

        }

    });



    /*

     * If your app is closed, you can check if it was opened by a notification being clicked / tapped / opened as follows:

     * */

    const notificationOpen = await firebase.notifications().getInitialNotification();

    if (notificationOpen) {

        const {
            title,
            body,
            secret_key,
            user_id,
            realm_id,
            user_os,
            user_location
        } = notificationOpen.notification.data;

        this.props.navigation.navigate('FCM', {
            title: title,
            body: body,

            secret_key: secret_key,
            user_id: user_id,
            realm_id: realm_id,
            user_os: user_os,
            user_location: user_location
        });

    }

    /*

     * Triggered for data only payload in foreground

     * */

    this.messageListener = firebase.messaging().onMessage((message) => {

        console.log("JSON.stringify:", JSON.stringify(message));

    });

}

如果需要更多细节,请告诉我。

编辑

我已更新代码。现在,我能够使firebase.messaging().onMessage()代码正常工作并在前台接收触发。但是当应用程序处于后台时仍无法获得通知。以下是我所做的更改。

const fcmToken = await firebase.messaging().getToken();

firebase.messaging().ios.registerForRemoteNotifications().then((flag)=>{
        console.log("registered", flag);
      }).catch((err)=>{
        console.log("message", err);
      });

AppDelegate.m

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import "RNFirebaseNotifications.h"
#import "RNFirebaseMessaging.h"


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
  [RNFirebaseNotifications configure];


  //[FIRApp configure];

  [Fabric with:@[[Crashlytics class]]];

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"CymmAuth"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}


- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
  [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
  [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}

-(void) userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {

  [[RNFirebaseMessaging instance] didReceiveRemoteNotification:response.notification.request.content.userInfo];
  completionHandler();
}

@end

请告诉我是否有遗漏。 firebase.notifications().onNotification() 未触发。


你使用的是哪个版本的react-native-firebase? - Leo Odishvili
"react-native-firebase": "^5.6.0" - Kuldeep Dubey
@ChristilynArjona 我正在物理设备上进行测试。已经创建了开发证书,也会尝试使用生产环境。 - Kuldeep Dubey
@LeoOdishvili 我已经更新了代码。现在逻辑的一部分正在工作。 - Kuldeep Dubey
@Kosalram,我已经解决了这个问题。将在答案中发布完整的程序。希望能对您有所帮助。 - Kuldeep Dubey
显示剩余3条评论
1个回答

17

经过参考多篇谷歌文章,我成功解决了问题。我意识到很多人都在面临这个问题,所以我把所有实现的步骤和代码都列出来了。

需要从苹果的开发者账户生成应用程序标识(App ID)和 APNs 密钥。在生成 App ID 和 APNs 密钥之后,将生成的 APNs 密钥添加到 Firebase 项目中。在添加了推送通知作为能力的 App ID 中,使用开发人员和生产服务 SSL 证书进行配置。

此外,请确保通过 Xcode 在项目名称下添加了 GoogleService-Info.plist 文件。

在 Xcode 的 Signing & Capabilities 中添加 Push Notifications and Background Modes > Remote notification, Background fetch, Background processing(确认能力是否反映在 Debug 和 Release 中)。

在 info.plist 中将 FIRAnalyticsDebugEnabled、FirebaseAppDelegateProxyEnabled、FirebaseScreenReportingEnabled 设置为 No

在 Xcode 的 Scheme > Edit Scheme... 中检查 Run 模式的 Build Configuration 是否设置为 Debug。这将有助于在调试设备上调试应用程序时在 Xcode 中生成控制台。

  1. 在 React 应用程序中运行 npm install --save react-native-firebase
  2. 更新 ios 项目中的 Podfile
    pod 'Firebase/Core' pod 'Firebase/Messaging' pod 'Firebase/Crashlytics' pod 'Firebase/Analytics' pod 'RNFirebase', :path => '../node_modules/react-native-firebase/ios'
  3. cd ios > pod install

获取 FCM 和 APNs 令牌的代码。

const fcmToken = await firebase.messaging().getToken();
      console.log("FCM_Token", fcmToken);

      firebase.messaging().ios.registerForRemoteNotifications().then((flag) => {
          firebase.messaging().ios.getAPNSToken().then(apns => {
            console.log("Apn Token", apns);
          }).catch((e) => {

          })
        }).catch((err) => {
          console.log("message", err);
        });

AppDelegate.m

#import "AppDelegate.h"
#import <React/RCTBridge.h>    
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>    
#import <Firebase.h>    
#import "RNFirebaseNotifications.h"    
#import "RNFirebaseMessaging.h"


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [FIRApp configure];
  [RNFirebaseNotifications configure];

  [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
  [application registerForRemoteNotifications];
  [Fabric with:@[[Crashlytics class]]];


  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge

                                                   moduleName:@"CymmAuth"

                                            initialProperties:nil];



  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];



  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

  UIViewController *rootViewController = [UIViewController new];

  rootViewController.view = rootView;

  self.window.rootViewController = rootViewController;

  [self.window makeKeyAndVisible];

  return YES;

}



- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge

{

#if DEBUG

  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

#else

  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

#endif

}

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
  [[RNFirebaseNotifications instance] didReceiveLocalNotification:notification];
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo
fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{
  [[RNFirebaseNotifications instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
  [[RNFirebaseMessaging instance] didRegisterUserNotificationSettings:notificationSettings];
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[FIRMessaging messaging].APNSToken = deviceToken;
}
@end

AppDelegate.h

#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
#import <Firebase.h>
#import <UserNotifications/UserNotifications.h>
@import UserNotifications; 
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>

@property (nonatomic, strong) UIWindow *window;

@end

这将在您的苹果设备上收到通知。

为了测试通知、FCM令牌有效性,并从APNs令牌重新生成有效的FCM令牌,Firebase提供了一个API调用。这可以作为额外的帮助进行测试。

  1. 发送推送通知

端点: https://fcm.googleapis.com/fcm/send
类型: POST
头: Authorization: "key:fcm_server_key"
正文: { "to": "fcm_token", "content_available": true, "mutable_content": true, "data": { "message": "Batman!", "mediaUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/2a/FloorGoban.JPG/1024px-FloorGoban.JPG" }, "notification": { "body": "Enter your message", "sound": "default" } }

  1. 验证您的FCM令牌

端点: https://iid.googleapis.com/iid/info/your_fcm_token
类型: GET
头: Authorization: "key:fcm_server_key"

  1. 使用APNs令牌重新生成FCM令牌

端点: https://iid.googleapis.com/iid/v1:batchImport
类型: POST
头: Authorization: "key:fcm_server_key"
正文: { "application":"package Id", "sandbox":true, "apns_tokens":[ "apnstoken 1","apnstoken 2" ] }

希望这有所帮助。谢谢。


谢谢您指出 APNs 密钥和证书的问题。使用 @react-native-firebase/messaging@10.4.1,我不必修改 AppDelegate.m 文件。 - Sarcastron
你没有指明在AppDelegate.mAppDelegate.h中做了哪些更改,也没有说明如何应用提供的自定义代码。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接