In our app, Firebase Dynamic Links stopped working some days ago without changing anything. This issue occurs on iOS only. We tested old releases of our app, and also old iOS versions, but the links don't work anywhere anymore. So we have no idea what can have changed and caused this issue.
The Xcode Console outputs the following Error when trying to open a dynamic link:
-[RNFirebaseLinks application:continueUserActivity:restorationHandler:]_block_invoke [Line 83] Failed to handle universal link: https://XXX.page.link/XXX
The app still opens, but the dispatchUrl callback is not called anymore:
Firebase.links().getInitialLink().then(this.dispatchUrl);
Firebase.links().onLink(this.dispatchUrl);
After uninstalling the app and installing it again, the link works one time initially, then stops working again.
We noticed, that Linking.getInitialURL()
works (only on iOS), but Linking.addEventListener('url', ...)
does not. So we still can't handle app links that are called while the app is running.
Here are some relevant files from our set-up:
package.json
{
"name": "XXX",
"version": "3.5.0",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest",
"tsc": "tsc",
"ios": "react-native run-ios --scheme Development --configuration Dev.Debug",
"ios-beta": "react-native run-ios --scheme Beta --configuration Beta.Debug",
"ios-prod": "react-native run-ios --scheme Production --configuration Production.Debug",
"ios iPhone 5s": "react-native run-ios --scheme Development --configuration Dev.Debug --simulator \"iPhone 5s\"",
"ios iPhone 6": "react-native run-ios --scheme Development --configuration Dev.Debug --simulator \"iPhone 6\"",
"ios iPhone 8": "react-native run-ios --scheme Development --configuration Dev.Debug --simulator \"iPhone 8\"",
"ios iPhone X": "react-native run-ios --scheme Development --configuration Dev.Debug --simulator \"iPhone X\"",
"ios iPhone 11": "react-native run-ios --scheme Development --configuration Dev.Debug --simulator \"iPhone 11\"",
"ios iPad (5th generation)": "react-native run-ios --scheme Development --configuration Dev.Debug --simulator \"iPad (5th generation)\"",
"android": "react-native run-android --variant=devDebug --appId=XXX",
"android-dev-release": "cd android && ./gradlew assembleDevRelease",
"android-dev-install": "adb install android/app/build/outputs/apk/dev/release/app-dev-release-unsigned.apk",
"android-beta": "react-native run-android --variant=betaDebug --appId=XXX",
"android-prod": "react-native run-android --variant=prodDebug",
"postinstall": "./node_modules/react-native-maps/enable-google-maps ./ios && rndebugger-open && react-native-schemes-manager all",
"postversion": "react-native-version --skip-tag --never-amend",
"git-local-prune": "git branch -vv | grep ': \\(gone\\|entfernt\\)]'| grep -v '\\*' | awk '{ print $1; }' | xargs git branch -d",
"xcode": "open ios/XXX.xcworkspace"
},
"dependencies": {
"@react-native-community/async-storage": "^1.6.1",
"@turf/distance": "^6.0.1",
"decko": "1.2.0",
"firebase": "^5.5.9",
"geofirestore": "^3.3.1",
"jsc-android": "224109.x.x",
"lottie-ios": "^2.5.0",
"lottie-react-native": "^2.5.10",
"mobx": "^5.15.4",
"mobx-react": "^5.3.3",
"moment": "^2.23.0",
"react": "^16.8.6",
"react-native": "^0.59.10",
"react-native-actionsheet": "^2.4.2",
"react-native-android-location-services-dialog-box": "^2.8.0",
"react-native-contacts": "^4.0.3",
"react-native-device-info": "^0.25.1",
"react-native-fabric": "0.5.2",
"react-native-fast-image": "~5.2.0",
"react-native-fbsdk": "^0.10.0",
"react-native-firebase": "5.2.1",
"react-native-google-signin": "^1.2.1",
"react-native-i18n": "^2.0.15",
"react-native-image-picker": "~0.28.0",
"react-native-image-progress": "~1.1.1",
"react-native-image-resizer": "~1.0.1",
"react-native-image-zoom-viewer": "2.2.24",
"react-native-maps": "0.23.0",
"react-native-permissions": "^1.1.1",
"react-native-progress": "~3.5.0",
"react-native-snackbar": "^1.0.2",
"react-native-snap-carousel": "~3.7.5",
"react-native-status-bar-height": "^2.2.0",
"react-native-svg": "^8.0.11",
"react-native-webview": "^5.12.1",
"react-native-youtube": "^1.1.0",
"react-navigation": "^2.18.0",
"rn-fetch-blob": "0.10.15",
"rn-placeholder": "~1.3.2",
"rn-viewpager": "~1.2.9",
"semver": "~5.6.0",
"styled-components": "3.4.9",
"ts-optchain": "~0.1.2",
"url-parse": "^1.4.4"
},
"devDependencies": {
"@babel/plugin-proposal-decorators": "^7.1.2",
"@babel/runtime": "^7.1.2",
"@types/jest": "^23.3.5",
"@types/lodash": "~4.14.120",
"@types/react": "^16.8.19",
"@types/react-native": "~0.57.60",
"@types/react-native-fbsdk": "^0.7.0",
"@types/react-native-i18n": "~2.0.0",
"@types/react-native-permissions": "^1.1.1",
"@types/react-native-snap-carousel": "~3.7.1",
"@types/react-native-status-bar-height": "^2.1.0",
"@types/react-navigation": "^2.0.24",
"@types/react-test-renderer": "^16.0.3",
"@types/semver": "~5.5.0",
"@types/url-parse": "^1.4.2",
"babel-jest": "23.6.0",
"jest": "23.6.0",
"marked": "^0.7.0",
"metro": "^0.54.0",
"metro-react-native-babel-preset": "^0.54.0",
"prettier": "^1.14.3",
"react-native-debugger-open": "~0.3.17",
"react-native-schemes-manager": "^1.0.5",
"react-native-version": "^2.6.7",
"react-test-renderer": "16.6.3",
"tslint": "^5.11.0",
"typescript": "^3.7.5"
},
"jest": {
"preset": "react-native"
},
"rnpm": {
"assets": [
"./src/assets/fonts/"
]
},
"prettier": {
"printWidth": 140,
"tabWidth": 4,
"useTabs": false,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"parser": "typescript"
},
"xcodeSchemes": {
"Debug": [
"Beta.Debug",
"Dev.Debug"
],
"Release": [
"Beta.Release",
"Dev.Release"
],
"projectDirectory": "ios"
}
}
ios/Podfile
target 'XXX' do
rn_path = '../node_modules/react-native'
rn_maps_path = '../node_modules/react-native-maps'
platform :ios, '9.0'
# Pods for XXX
pod 'React', :path => rn_path, :subspecs => [
'Core',
'CxxBridge',
'DevSupport',
'RCTActionSheet',
'RCTAnimation',
'RCTGeolocation',
'RCTImage',
'RCTLinkingIOS',
'RCTNetwork',
'RCTSettings',
'RCTText',
'RCTVibration',
'RCTWebSocket',
]
pod 'yoga', :path => "#{rn_path}/ReactCommon/yoga"
pod 'RNI18n', :path => '../node_modules/react-native-i18n'
pod 'lottie-ios', :path => '../node_modules/lottie-ios'
pod 'lottie-react-native', :path => '../node_modules/lottie-react-native'
pod 'react-native-fast-image', :path => '../node_modules/react-native-fast-image'
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'ReactNativePermissions', :path => '../node_modules/react-native-permissions'
# Required by RNFirebase
pod 'Firebase/Core', '~> 5.14.0'
pod 'Firebase/Auth', '~> 5.14.0'
pod 'Firebase/DynamicLinks', '~> 5.14.0'
pod 'Firebase/Firestore', '~> 5.14.0'
pod 'Firebase/Messaging', '~> 5.14.0'
pod 'Firebase/Database', '~> 5.14.0'
pod 'Firebase/RemoteConfig', '~> 5.14.0'
# Google Tag Manager
pod 'GoogleTagManager', '~> 7.0'
# Crashlytics
pod 'Fabric', '~> 1.7.13'
pod 'Crashlytics', '~> 3.10.7'
pod 'ReactNativeFabric', :path => '../node_modules/react-native-fabric'
# React Native third party dependencies podspecs
pod 'DoubleConversion', :podspec => "#{rn_path}/third-party-podspecs/DoubleConversion.podspec"
#pod 'glog', :podspec => "#{rn_path}/third-party-podspecs/glog.podspec"
pod 'Folly', :podspec => "#{rn_path}/third-party-podspecs/Folly.podspec"
# react-native-maps dependencies
pod 'react-native-maps', path: rn_maps_path
pod 'react-native-google-maps', path: rn_maps_path # Unomment this line if you want to support GoogleMaps on iOS
pod 'GoogleMaps' # Uncomment this line if you want to support GoogleMaps on iOS
pod 'Google-Maps-iOS-Utils' # Uncomment this line if you want to support GoogleMaps on iOS
# Youtube dependencies
pod 'react-native-youtube', :path => '../node_modules/react-native-youtube'
pod 'XCDYouTubeKit', '~> 2.5'
pod 'react-native-image-picker', :path => '../node_modules/react-native-image-picker'
pod 'RNGoogleSignin', :path => '../node_modules/react-native-google-signin'
pod 'GoogleSignIn', '~> 4.4.0'
pod 'react-native-fbsdk', :path => '../node_modules/react-native-fbsdk'
# https://github.com/facebook/react-native-fbsdk/issues/509
pod 'FBSDKCoreKit', '~> 5.0.0'
pod 'FBSDKLoginKit', '~> 5.0.0'
pod 'FBSDKShareKit', '~> 5.0.0'
pod 'RNSnackbar', :path => '../node_modules/react-native-snackbar'
pod 'rn-fetch-blob', :path => '../node_modules/rn-fetch-blob'
pod 'react-native-image-resizer', :path => '../node_modules/react-native-image-resizer'
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
target 'XXXTests' do
inherit! :search_paths
# Pods for testing
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'react-native-google-maps'
target.build_configurations.each do |config|
config.build_settings['CLANG_ENABLE_MODULES'] = 'No'
end
end
if target.name == "React"
target.remove_from_project
end
end
system('node ./generatePodsHtml.js')
end
AppDelegate.m
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "AppDelegate.h"
#import "RNFirebaseLinks.h"
#import "RNFirebaseNotifications.h"
#import "RNFirebaseMessaging.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import <GoogleMaps/GoogleMaps.h>
#import <RNGoogleSignin/RNGoogleSignin.h>
#import <FBSDKCoreKit/FBSDKCoreKit.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *path = [[NSBundle mainBundle] pathForResource: @"Info" ofType: @"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: path];
NSString *apiKey = [dict objectForKey: @"GOOGLE_API_KEY"];
[GMSServices provideAPIKey:apiKey];
[FIROptions defaultOptions].deepLinkURLScheme = @"XXX";
[FIRApp configure];
// [FIRDatabase database].persistenceEnabled = YES;
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
[RNFirebaseNotifications configure];
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"XXX"
initialProperties:nil
launchOptions:launchOptions];
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;
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<NSString *, id> *)options {
BOOL handled = [[RNFirebaseLinks instance] application:application openURL:url options:options];
if (!handled) {
handled = [RNGoogleSignin application:application
openURL:url
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
}
if (!handled) {
handled = [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
}
if (!handled) {
handled = [RCTLinkingManager application:application openURL:url options:options];
}
return handled;
}
-(BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler {
return [[RNFirebaseLinks instance] application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
}
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(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