invertase / react-native-firebase

🔥 A well-tested feature-rich modular Firebase implementation for React Native. Supports both iOS & Android platforms for all Firebase services.
https://rnfirebase.io
Other
11.66k stars 2.21k forks source link

[🐛] 🔥 In App Messaging Button Doesn't Work on iOS #7846

Open paranat opened 3 months ago

paranat commented 3 months ago

Issue

I created a draft In-App message of type Card with a button that links to my company's intranet site (https://custweb.paragontech.com). I sent it out using Test on Device. The message was successfully received and opened on my test device, but when I clicked on the button it just closed the message instead of opening the link.

Screenshot 2024-06-17 at 1 48 38 PM

I am using react-native with the latest version of all firebase packages.

 "@react-native-firebase/analytics": "^20.1.0",
 "@react-native-firebase/app": "^20.1.0",
 "@react-native-firebase/in-app-messaging": "^20.1.0",
 "@react-native-firebase/messaging": "^20.1.0",

This seems to be related to https://github.com/invertase/react-native-firebase/issues/7730 and https://github.com/invertase/react-native-firebase/issues/6861, both of which were closed as stale without resolution.

Relevant XCode Output:

[FirebaseInAppMessaging][I-IAM400031] A test message clicked. Do test event impression/click analytics logging
2024-06-17 14:06:05.706757-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInstallations][I-FIS002001] -[FIRInstallationsIDController installationWithValidAuthTokenForcingRefresh:0], appName: __FIRAPP_DEFAULT
2024-06-17 14:06:05.708042-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInstallations][I-FIS002000] -[FIRInstallationsIDController createGetInstallationItemPromise], appName: __FIRAPP_DEFAULT
2024-06-17 14:06:05.709135-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInAppMessaging][I-IAM400037] Following action url https://custweb.paragontech.com
2024-06-17 14:06:05.709810-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInAppMessaging][I-IAM240007] Following action url https://custweb.paragontech.com
2024-06-17 14:06:05.710339-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInAppMessaging][I-IAM240001] Try to treat it as a universal link.
2024-06-17 14:06:05.711388-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInAppMessaging][I-IAM240004] App delegate responds to application:continueUserActivity:restorationHandler:.Simulating action url opening from a web browser.
2024-06-17 14:06:05.718852-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInAppMessaging][I-IAM240005] App handling acton URL returns YES, no more further action taken
2024-06-17 14:06:05.718927-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInAppMessaging][I-IAM400034] Seeing success from following action URL
2024-06-17 14:06:05.719083-0400 Dragon AppStore[46487:1280012] 10.27.0 - [FirebaseInAppMessagingDisplay][I-FID200001] [FIDBaseRenderingViewController dealloc] triggered

Project Files

Javascript

Click To Expand

#### `package.json`: ```json { "name": "Stocked", "version": "2.1.8", "private": true, "config": { "deploy_url": "https://custweb.paragontech.com/apps/dragon/downloads" }, "scripts": { "bundle:install": "bundle config set path '.' && bundle install", "build:ios": "cd ./ios && BUNDLE_GEMFILE=../Gemfile bundle exec fastlane build scheme:Dragon", "build:appstore": "cd ./ios && BUNDLE_GEMFILE=../Gemfile bundle exec fastlane build scheme:AppStore", "build:android": "cd ./android && ./gradlew clean && ./gradlew assembleRelease", "android": "react-native run-android", "ios": "react-native run-ios", "lint": "eslint .", "start": "react-native start", "test": "jest", "version": "node scripts/update_version_file.js", "postversion": "react-native-version", "bump-build": "react-native-version -b", "deploy": "./scripts/deploy.sh" }, "dependencies": { "@notifee/react-native": "^7.8.2", "@react-native-async-storage/async-storage": "^1.21.0", "@react-native-firebase/analytics": "^20.1.0", "@react-native-firebase/app": "^20.1.0", "@react-native-firebase/in-app-messaging": "^20.1.0", "@react-native-firebase/messaging": "^20.1.0", "@react-native-masked-view/masked-view": "^0.3.1", "@react-navigation/bottom-tabs": "^6.5.2", "@react-navigation/native": "^6.1.1", "@react-navigation/native-stack": "^6.9.7", "@rneui/base": "^4.0.0-rc.7", "@rneui/themed": "^4.0.0-rc.7", "expo": "^50.0.4", "expo-web-browser": "~12.8.2", "metro-babel-register": "^0.80.5", "prop-types": "^15.8.1", "react": "18.2.0", "react-native": "0.73.4", "react-native-app-link": "^1.0.1", "react-native-biometrics": "^3.0.1", "react-native-config": "^1.5.0", "react-native-device-info": "~10.12.0", "react-native-freshchat-sdk": "^4.4.0", "react-native-gesture-handler": "~2.14.1", "react-native-reanimated": "~3.6.2", "react-native-safe-area-context": "^4.7", "react-native-screens": "^3.18.2", "react-native-sensitive-info": "^6.0.0-alpha.9", "react-native-textinput-effects": "^0.6.1", "react-native-url-polyfill": "^2.0.0", "react-native-vector-icons": "^10.0.3", "react-native-webview": "^13.6.4", "react-navigation-props-mapper": "^3.0", "react-redux": "^8.1.3", "redux": "^4.0.5", "redux-persist": "^6.0.0", "redux-persist-sensitive-storage": "^1.0.0", "redux-thunk": "^2.3.0", "semver": "^7.3.2" }, "devDependencies": { "@babel/core": "^7.20.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0-0", "@babel/plugin-proposal-optional-chaining": "^7.0.0-0", "@babel/plugin-transform-arrow-functions": "^7.0.0-0", "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", "@babel/plugin-transform-template-literals": "^7.0.0-0", "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", "@react-native/babel-preset": "0.73.21", "@react-native/eslint-config": "0.73.2", "@react-native/metro-config": "0.73.5", "@react-native/typescript-config": "0.73.1", "@testing-library/jest-native": "^5.4.1", "@testing-library/react-native": "~11.4.0", "@types/react": "^18.2.6", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.6.3", "babel-plugin-module-resolver": "^5.0.0", "eslint": "^8.19.0", "jest": "^29.6.3", "jest-date-mock": "^1.0.8", "jest-fetch-mock": "^3.0.3", "jetifier": "^1.6.8", "npm-license-crawler": "^0.2.1", "prettier": "2.8.8", "react-dom": "18.2.0", "react-native-eject": "^0.2.0", "react-native-version": "^4.0.0", "react-test-renderer": "18.2.0", "redux-mock-store": "^1.5.4", "typescript": "5.0.4" }, "engines": { "node": ">=18" } } ``` #### `firebase.json` for react-native-firebase v6: ```json { "react-native": { "google_analytics_automatic_screen_reporting_enabled": false } } ```

iOS

Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like: ```ruby require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking") # Resolve react_native_pods.rb with node to allow for hoisting require Pod::Executable.execute_command('node', ['-p', 'require.resolve( "react-native/scripts/react_native_pods.rb", {paths: [process.argv[1]]}, )', __dir__]).strip platform :ios, min_ios_version_supported prepare_react_native_project! # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded # # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` # ```js # module.exports = { # dependencies: { # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), # ``` flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled $RNFirebaseAnalyticsWithoutAdIdSupport = true linkage = ENV['USE_FRAMEWORKS'] if linkage != nil Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green use_frameworks! :linkage => linkage.to_sym end abstract_target 'Dragon Targets' do use_expo_modules! post_integrate do |installer| begin expo_patch_react_imports!(installer) rescue => e Pod::UI.warn e end begin expo_patch_react_imports!(installer) rescue => e Pod::UI.warn e end end config = use_native_modules! use_frameworks! :linkage => :static use_react_native!( :path => config[:reactNativePath], # Enables Flipper. # # Note that if you have use_frameworks! enabled, Flipper will not work and # you should disable the next line. # :flipper_configuration => flipper_config, # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) target 'DragonTests' do inherit! :complete # Pods for testing end target 'Dragon' target 'Dragon AppStore' post_install do |installer| # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 react_native_post_install( installer, config[:reactNativePath], :mac_catalyst_enabled => false ) # This is necessary for Xcode 14, because it signs resource bundles by default # when building for devices. installer.target_installation_results.pod_target_installation_results .each do |pod_name, target_installation_result| target_installation_result.resource_bundle_targets.each do |resource_bundle_target| resource_bundle_target.build_configurations.each do |config| config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO' end end end installer.pods_project.targets.each do |target| target.build_configurations.each do |config| if Gem::Version.new('12.0') > Gem::Version.new(config.build_settings['IPHONEOS_DEPLOYMENT_TARGET']) config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' end end end end end ``` #### `AppDelegate.mm`: ```objc #import "AppDelegate.h" #import #import #import @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [FIRApp configure]; self.moduleName = @"Dragon"; // You can add your custom initial props in the dictionary below. // They will be passed down to the ViewController used by React Native. self.initialProps = @{}; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { return [self getBundleURL]; } - (NSURL *)getBundleURL { #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 *)options { return [RCTLinkingManager application:application openURL:url options:options]; } - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler { return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; } @end ```


Environment

Click To Expand

**`react-native info` output:** ``` System: OS: macOS 14.4.1 CPU: (8) arm64 Apple M2 Memory: 104.08 MB / 16.00 GB Shell: version: 3.6.1 path: /opt/homebrew/bin/fish Binaries: Node: version: 18.18.2 path: /var/folders/3s/62zs9d2s1z39gyxyh3p2klm4g4rbz5/T/yarn--1718647083368-0.15506613156732874/node Yarn: version: 1.22.22 path: /var/folders/3s/62zs9d2s1z39gyxyh3p2klm4g4rbz5/T/yarn--1718647083368-0.15506613156732874/yarn npm: version: 9.8.1 path: ~/.nvm/versions/node/v18.18.2/bin/npm Watchman: Not Found Managers: CocoaPods: Not Found SDKs: iOS SDK: Platforms: - DriverKit 23.2 - iOS 17.2 - macOS 14.2 - tvOS 17.2 - visionOS 1.0 - watchOS 10.2 Android SDK: Not Found IDEs: Android Studio: 2023.1 AI-231.9392.1.2311.11330709 Xcode: version: 15.2/15C500b path: /usr/bin/xcodebuild Languages: Java: version: 17.0.11 path: /usr/bin/javac Ruby: version: 2.7.6 path: /Users/nskiba/.rbenv/shims/ruby npmPackages: "@react-native-community/cli": Not Found react: installed: 18.2.0 wanted: 18.2.0 react-native: installed: 0.73.4 wanted: 0.73.4 react-native-macos: Not Found npmGlobalPackages: "*react-native*": Not Found Android: hermesEnabled: true newArchEnabled: false iOS: hermesEnabled: true newArchEnabled: false ``` - **Platform that you're experiencing the issue on**: - [x] iOS - [ ] Android - [ ] **iOS** but have not tested behavior on Android - [ ] **Android** but have not tested behavior on iOS - [ ] Both - **`react-native-firebase` version you're using that has this issue:** - `20.1.0` - **`Firebase` module(s) you're using that has the issue:** - `in-app-messaging` - **Are you using `TypeScript`?** - `N`


paranat commented 3 months ago

I believe I've found the issue. Having followed the instructions to enable Deep Linking on startup for a react-native application, the handlers in my AppDelegate.mm file conflict with the ones set up by react-native firebase. Fortunately I don't need to handle Deep Links to my app on app launch, so I can remove the offending handlers from my AppDelegate.mm for the moment. That said, it may be worthwhile to look into whether an alternate method can be used that doesn't conflict with the Deep Linking configuration found here: https://reactnative.dev/docs/linking?language=javascript#enabling-deep-links

nailavann commented 3 months ago

The problem continues. It is fixed when I remove the Linking API and Universal API lines in the AppDelegate.mm file. But is this a solution?

mikehardy commented 2 months ago

Hey there 👋 - looked into this a bit today and it appears something in your app is implementing AppDelegage:restorationHandler and it returns a YES that it handled the FIAM linking attempt, which shortcuts all further attempts to process it.

Does this sound correct for your app? An examination of restorationHandler implementations on AppDelegate might be informative

Ref: https://github.com/firebase/firebase-ios-sdk/blob/e668c846d81487ddd8b26729765da8e772bbde6b/FirebaseInAppMessaging/Sources/Runtime/FIRIAMActionURLFollower.m#L173-L195

We do have a restorationHandler in dynamic links in case you have not removed that yet, but it appears we return NO in all cases, so I don't believe it's from our implementation here in react-native-firebase at least (ref https://github.com/invertase/react-native-firebase/blob/c2c457608c865f6d25e4b9b6689cbc00721de194/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.m#L80)

mariushorvat commented 1 month ago

I'm getting the same issue. Since we can't using Firebase deeplinks due to deprecation I haven't found other solutions around.

thassis commented 1 month ago

I'm experiencing the same issue but found a workaround. Interestingly, the Linking.addEventListener('url', callback) is triggered when the user clicks on a banner with a link. This allowed me to use Linking itself to try reopening the URL.

Here's a snippet of the code I added in App.tsx:

`useEffect(() => { const listener = Linking.addEventListener('url', handleOpenURL); return () => { listener.remove(); }; }, []);

const handleOpenURL = async (event) => { const { url } = event; Linking.openURL(url); };`

Hope this helps!

github-actions[bot] commented 1 week ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.