Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: iOS in app messages not working in foreground with notifee #229

Open
DanMichaeli1 opened this issue Aug 22, 2023 · 2 comments
Open
Labels

Comments

@DanMichaeli1
Copy link

Which Platforms?

iOS

Which React Native Version?

0.71.7

Which @braze/react-native-sdk SDK version?

6.0.2

Repro Rate

100%

Steps To Reproduce

install braze 6.0.2
install notifee 7.8.0

IAM:

  1. Open iOS app
  2. Send test in app message to user in Braze campaign UI
  3. Click on "Tap to see Test In-App Message"

Expected Behavior

expected to display the IAM.

Actual Incorrect Behavior

IAM isn't displayed. After going to background/closing and reopening the app, the IAM appears.

Verbose Logs

No response

Additional Information

Seems like notifee is intercepting braze's foreground events and not getting handled by braze sdk.

Is there a way to call braze's UI IAM handler in js layer?

my AppDelegate.mm braze setup:

#import "AppDelegate.h"
#import <Firebase.h>
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "RNCConfig.h"
#import <React/RCTLinkingManager.h>
#import "BrazeReactUtils.h"

...

@implementation AppDelegate

static Braze *_braze;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

...

  // Braze setup
  NSString *brazeApiKey = [RNCConfig envFor:configApiKey];
  NSString *brazeUrl = [RNCConfig envFor:@"BRAZE_SDK_ENDPOINT"];
  BRZConfiguration *configuration = [[BRZConfiguration alloc] initWithApiKey:brazeApiKey endpoint:brazeUrl];
  configuration.triggerMinimumTimeInterval = 1;
  configuration.logger.level = BRZLoggerLevelInfo;
  Braze *braze = [BrazeReactBridge initBraze:configuration];
  braze.delegate = [[BrazeReactDelegate alloc] init];
  AppDelegate.braze = braze;

  [self registerForPushNotifications];
  [[BrazeReactUtils sharedInstance] populateInitialUrlFromLaunchOptions:launchOptions];


  if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) {
    [AppDelegate.braze notifications];
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    UNAuthorizationOptions options = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
    if (@available(iOS 12.0, *)) {
    options = options | UNAuthorizationOptionProvisional;
      [center setNotificationCategories:BRZNotifications.categories];
       [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
  } else {
    UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound) categories:nil];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
  }
  
  if ([FIRApp defaultApp] == nil) {
    [FIRApp configure];
  }
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"..."
                                            initialProperties:nil];


  if (@available(iOS 13.0, *)) {
      rootView.backgroundColor = [UIColor systemBackgroundColor];
  } else {
      rootView.backgroundColor = [UIColor whiteColor];
  }
  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

#pragma mark - Push Notifications

- (void)registerForPushNotifications {
  UNUserNotificationCenter *center = UNUserNotificationCenter.currentNotificationCenter;
  [center setNotificationCategories:BRZNotifications.categories];
  center.delegate = self;
  [UIApplication.sharedApplication registerForRemoteNotifications];
  // Authorization is requested later in the JavaScript layer via `Braze.requestPushPermission`.
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  
  [AppDelegate.braze.notifications registerDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    if (notificationSettings.types != UIUserNotificationTypeNone) {
        [application registerForRemoteNotifications];
    }
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  BOOL processedByBraze = AppDelegate.braze != nil && [AppDelegate.braze.notifications handleBackgroundNotificationWithUserInfo:userInfo
                                                                                                         fetchCompletionHandler:completionHandler];
  if (processedByBraze) {
    return;
  }

  completionHandler(UIBackgroundFetchResultNoData);
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
  didReceiveNotificationResponse:(UNNotificationResponse *)response
         withCompletionHandler:(void (^)(void))completionHandler {
  [[BrazeReactUtils sharedInstance] populateInitialUrlForCategories:response.notification.request.content.userInfo];
  BOOL processedByBraze = AppDelegate.braze != nil && [AppDelegate.braze.notifications handleUserNotificationWithResponse:response
                                                                                                    withCompletionHandler:completionHandler];
  if (processedByBraze) {
    return;
  }

  completionHandler();
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
  if (@available(iOS 14.0, *)) {
    completionHandler(UNNotificationPresentationOptionList | UNNotificationPresentationOptionBanner);
  } else {
    completionHandler(UNNotificationPresentationOptionAlert);
  }
}

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

- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  [RCTLinkingManager application:application openURL:url options:options];
  [[AppsFlyerAttribution shared] handleOpenUrl:url options:options];
  return YES;
}


- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
 restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
  [[AppsFlyerAttribution shared] continueUserActivity:userActivity restorationHandler:restorationHandler];
  return [RCTLinkingManager application:application
                   continueUserActivity:userActivity
                     restorationHandler:restorationHandler];
}

#pragma mark - Helpers

+ (Braze *)braze {
  return _braze;
}

+ (void)setBraze:(Braze *)braze {
  _braze = braze;
}

/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
///
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
/// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`.
- (BOOL)concurrentRootEnabled
{
  return true;
}



@end

@hokstuff
Copy link
Collaborator

Hi @DanMichaeli1,

It sounds like notifee is not compatible with the Braze React Native SDK. Does the subscribeToInAppMessages API accommodate for your use case? Otherwise, there isn't a direct way to reference the Braze UI IAM handler in the JS layer.

Additionally, can you contact support@braze.com with verbose logs and any other relevant information around how notifee works with push notifications that may interfere with the Braze SDK? Please also link this public issue in your ticket.

Thanks!

@Minishlink
Copy link

Minishlink commented Sep 12, 2023

Hello, see invertase/notifee#236 (review)

In summary use this patch (for example with patch-package) in the meantime:

diff --git a/node_modules/@notifee/react-native/ios/NotifeeCore/NotifeeCoreUtil.m b/node_modules/@notifee/react-native/ios/NotifeeCore/NotifeeCoreUtil.m
index 7acf143..dee65b8 100644
--- a/node_modules/@notifee/react-native/ios/NotifeeCore/NotifeeCoreUtil.m
+++ b/node_modules/@notifee/react-native/ios/NotifeeCore/NotifeeCoreUtil.m
@@ -584,6 +584,8 @@ + (NSNumber *)convertToTimestamp:(NSDate *)date {
   return [NSNumber numberWithDouble:([date timeIntervalSince1970] * 1000)];
 }
 
+static NSString *const AppboyAPNSDictionaryKey = @"ab";
+
 /**
  * Parse UNNotificationRequest to NSDictionary
  *
@@ -597,6 +599,11 @@ + (NSMutableDictionary *)parseUNNotificationRequest:(UNNotificationRequest *)req
 
   NSDictionary *userInfo = request.content.userInfo;
   
+    
+  if (userInfo != nil && userInfo[AppboyAPNSDictionaryKey] != nil) {
+      return nil;
+  }
+
   // Check for remote details
   if ([request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
     NSMutableDictionary *remote = [NSMutableDictionary dictionary];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants