React-native-firebase: 馃敟 Dynamic Link is not working when IOS app is opened in background

Created on 13 Jan 2020  路  3Comments  路  Source: invertase/react-native-firebase


Issue



Dynamic Link is not working when IOS app is in background because It is delivering wrong url .
After App is destroyed it is delivering correct url and opens correct location.
On Android in both cases works fine.

When app is in background:
dynamic-link-issue

After app destroyed:
dynamic-link-issue-2


Project Files






Javascript

Click To Expand

#### `package.json`:

{
  "name": "CPApp",
  "version": "1.32.0",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint .",
    "clean": "./scripts/clean-react.sh",
    "clean-ios": "./scripts/clean-ios.sh",
    "android-int": "ENVFILE=.env.integration react-native run-android",
    "android-localhost": "export ENVFILE=.env.local.android && react-native run-android",
    "android-stg": "ENVFILE=.env.stg react-native run-android",
    "android-prod": "ENVFILE=.env.prod react-native run-android",
    "android-log": "ENVFILE=.env.log react-native run-android",
    "android-int-release": "ENVFILE=.env.dev.integration react-native run-android --variant='release'",
    "android-stg-release": "ENVFILE=.env.stg react-native run-android --variant='release'",
    "android-prod-release": "ENVFILE=.env.prod react-native run-android --variant='release'",
    "build-android-int": "export ENVFILE=.env.dev.integration && cd android && ./gradlew assembleRelease && cd ..",
    "build-android-demo": "export ENVFILE=.env.demo && cd android && ./gradlew assembleRelease && cd ..",
    "build-android-stg": "export ENVFILE=.env.stg && cd android && ./gradlew assembleRelease && cd ..",
    "build-android-prod": "./scripts/build-android-release.sh",
    "bundle-android-prod": "./scripts/build-android-release.sh bundle",
    "prettier": "prettier 'src/**/*.js'",
    "flow": "flow",
    "postinstall": "./scripts/post-install.sh",
    "postversion": "react-native-version",
    "e2e-ios-debug-build": "detox build -c ios.sim.debug",
    "e2e-ios-debug": "detox test -c ios.sim.debug"
  },
  "dependencies": {
    "@mapbox/polyline": "1.0.0",
    "@mapbox/react-native-mapbox-gl": "https://github.com/oroundo-tech/react-native-mapbox-gl#fix/react_native_0.59",
    "@react-native-community/async-storage": "1.6.3",
    "@react-native-community/google-signin": "3.0.3",
    "@react-native-community/netinfo": "4.6.1",
    "@react-native-community/push-notification-ios": "1.0.3",
    "@react-native-community/viewpager": "3.1.0",
    "@react-native-firebase/analytics": "6.2.0",
    "@react-native-firebase/app": "6.2.0",
    "@react-native-firebase/dynamic-links": "6.2.0",
    "abortcontroller-polyfill": "1.2.1",
    "appcenter": "2.6.0",
    "appcenter-analytics": "2.6.0",
    "appcenter-crashes": "2.6.0",
    "base-64": "0.1.0",
    "currency-formatter": "1.5.3",
    "deepmerge": "4.2.2",
    "eslint-config-prettier": "5.0.0",
    "lodash.debounce": "4.0.8",
    "lodash.difference": "4.5.0",
    "lodash.intersection": "4.4.0",
    "lodash.isequal": "4.5.0",
    "lodash.throttle": "4.1.1",
    "lottie-ios": "3.1.3",
    "lottie-react-native": "3.3.1",
    "moment": "2.22.2",
    "point-in-polygon": "1.0.1",
    "prop-types": "15.6.2",
    "react": "16.9.0",
    "react-enum-prop-type": "0.1.0",
    "react-native": "0.61.5",
    "react-native-action-sheet-xg": "https://github.com/oroundo-tech/react-native-action-sheet",
    "react-native-android-back-button": "https://github.com/oroundo-tech/react-native-android-back-button.git",
    "react-native-android-badge": "0.4.3",
    "react-native-android-location-services-dialog-box": "2.8.2",
    "react-native-app-intro": "https://github.com/oroundo-tech/react-native-app-intro.git",
    "react-native-audio-jack": "https://github.com/oroundo-tech/react-native-audio-jack#rn061",
    "react-native-autocomplete-input": "4.1.0",
    "react-native-billing": "3.0.0",
    "react-native-bluetooth-state": "https://github.com/Artirigo/react-native-bluetooth-state.git",
    "react-native-camera": "3.13.1",
    "react-native-code-push": "5.7.0",
    "react-native-config": "0.12.0",
    "react-native-device-info": "5.3.1",
    "react-native-exception-handler": "2.10.8",
    "react-native-fbsdk": "1.1.1",
    "react-native-fs": "2.16.2",
    "react-native-geolocation-service": "3.1.0",
    "react-native-gesture-handler": "1.5.2",
    "react-native-google-places-autocomplete": "https://github.com/oroundo-tech/react-native-google-places-autocomplete",
    "react-native-heading": "https://github.com/oroundo-tech/react-native-heading",
    "react-native-hyperlink": "0.0.16",
    "react-native-i18n": "2.0.15",
    "react-native-image-crop-picker": "0.26.1",
    "react-native-image-gallery": "https://github.com/oroundo-tech/react-native-image-gallery",
    "react-native-in-app-utils": "6.0.2",
    "react-native-keep-awake": "4.0.0",
    "react-native-kontaktio": "2.7.0",
    "react-native-linear-gradient": "2.5.6",
    "react-native-loading-placeholder": "0.0.6",
    "react-native-markdown-renderer": "3.2.8",
    "react-native-offline": "5.2.0",
    "react-native-onesignal": "3.5.0",
    "react-native-permissions": "2.0.8",
    "react-native-radio-buttons": "1.0.0",
    "react-native-reanimated": "1.4.0",
    "react-native-render-html": "4.1.2",
    "react-native-restart": "0.0.13",
    "react-native-screens": "2.0.0-alpha.8",
    "react-native-scrollable-tab-view": "1.0.0",
    "react-native-simple-toast": "https://github.com/vonovak/react-native-simple-toast",
    "react-native-slider": "0.11.0",
    "react-native-snap-carousel": "3.8.4",
    "react-native-sound": "https://github.com/oroundo-tech/react-native-sound#rn061",
    "react-native-tab-view": "https://github.com/oroundo-tech/react-native-tab-view",
    "react-native-webview": "7.6.0",
    "react-navigation": "4.0.10",
    "react-navigation-stack": "1.7.3",
    "react-navigation-tabs": "2.5.2",
    "react-redux": "7.1.3",
    "realm": "3.5.0",
    "redux": "4.0.1",
    "redux-action-buffer": "1.2.0",
    "redux-define": "1.1.1",
    "redux-logger": "3.0.6",
    "redux-persist": "4.10.2",
    "redux-thunk": "2.3.0",
    "regenerator-runtime": "0.13.1",
    "reselect": "4.0.0",
    "rn-fetch-blob": "0.11.2",
    "url-parse": "1.4.4",
    "validator": "10.9.0"
  },
  "devDependencies": {
    "@babel/core": "7.7.4",
    "@babel/preset-flow": "7.7.4",
    "@babel/runtime": "7.7.4",
    "@react-native-community/eslint-config": "0.0.5",
    "babel-eslint": "10.0.3",
    "babel-jest": "24.9.0",
    "babel-plugin-transform-remove-console": "6.9.4",
    "enzyme": "3.10.0",
    "enzyme-adapter-react-16": "1.15.1",
    "enzyme-to-json": "3.4.3",
    "eslint": "6.7.2",
    "eslint-config-standard": "14.1.0",
    "eslint-plugin-import": "2.18.2",
    "eslint-plugin-node": "10.0.0",
    "eslint-plugin-prettier": "3.1.1",
    "eslint-plugin-promise": "4.2.1",
    "eslint-plugin-react": "7.17.0",
    "eslint-plugin-react-native": "3.8.1",
    "eslint-plugin-standard": "4.0.1",
    "flow-bin": "0.113.0",
    "eslint-plugin-react-hooks": "2.3.0",
    "jest": "24.9.0",
    "jest-cli": "24.9.0",
    "jsdom": "15.2.1",
    "jsdom-global": "3.0.2",
    "metro-react-native-babel-preset": "0.57.0",
    "mocha": "6.2.2",
    "nock": "11.7.0",
    "prettier": "1.19.1",
    "react-dom": "16.12.0",
    "react-native-version": "3.2.0",
    "react-test-renderer": "16.9.0",
    "redux-mock-store": "1.5.3"
  },
  "jest": {
    "collectCoverage": false,
    "verbose": true,
    "preset": "react-native",
    "setupFiles": [
      "./.testsetup.js"
    ],
    "snapshotSerializers": [
      "<rootDir>/node_modules/enzyme-to-json/serializer"
    ],
    "transformIgnorePatterns": [
      "node_modules/(?!(react-native|react-native-i18n|my-project|react-navigation|react-native-kontaktio|react-native-linear-gradient|react-native-permissions|@mapbox|react-native-swiper|react-native-android-back-button|react-native-image-gallery|react-native-scrollable-tab-view|react-native-action-sheet-xg|react-native-image-crop-picker|react-native-device-info|react-native-offline|react-native-markdown-renderer|react-native-radio-buttons|react-native-camera|react-native-keep-awake|@mapbox/react-native-mapbox-gl|react-native-bluetooth-state|react-native-app-intro)/)"
    ],
    "globals": {
      "__DEV__": true
    }
  },
  "prettier": {
    "jsxBracketSameLine": true,
    "semi": false,
    "singleQuote": true,
    "tabWidth": 2,
    "printWidth": 120,
    "eslintIntegration": true,
    "parser": "flow"
  },
  "detox": {
    "test-runner": "mocha",
    "configurations": {
      "ios.sim.debug": {
        "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/CPApp.app",
        "build": "xcodebuild -workspace ios/CPApp.xcworkspace -scheme CPApp -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
        "type": "ios.simulator",
        "name": "iPhone 6"
      },
      "android.emu.debug": {
        "binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk",
        "build": "export ENVFILE=.env.dev && cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..",
        "type": "android.attached",
        "name": "192.168.56.101:5555"
      },
      "android.emu.release": {
        "binaryPath": "android/app/build/outputs/apk/release/app-release.apk",
        "build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..",
        "type": "android.attached",
        "name": "192.168.56.101:5555"
      }
    }
  }
}

#### `firebase.json` for react-native-firebase v6:
# N/A
### iOS
Click To Expand

#### `ios/Podfile`: - [ ] I'm not using Pods - [x] I'm using Pods and my Podfile looks like:

platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
target 'CPApp' do
  # Pods for CPApp
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
  pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
  pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
  pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
  pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
  pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
  pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
  pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
  pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
  pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
  pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
  pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
  pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
  pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

  # Custom pods for CPApp added manually after project initialisation
  pod 'react-native-geolocation', path: '../node_modules/@react-native-community/geolocation'
  permissions_path = '../node_modules/react-native-permissions/ios'
  pod 'Permission-Camera', :path => "#{permissions_path}/Camera.podspec"
  pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse.podspec"
  pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications.podspec"

  target 'CPAppTests' do
    inherit! :search_paths
    # Pods for testing
  end

  use_native_modules!
end

#### `AppDelegate.m`:
/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#import <React/RCTLinkingManager.h>
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <RNGoogleSignin/RNGoogleSignin.h>

#import <ReactNativeExceptionHandler.h>
#import <CodePush/CodePush.h>
#import <Firebase.h>

#import <AppCenterReactNative.h>
#import <AppCenterReactNativeAnalytics.h>
#import <AppCenterReactNativeCrashes.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"CPApp"
                                            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];

  // FIREBASE INITIALISATION
  [FIROptions defaultOptions].deepLinkURLScheme = @"firebaseLink";
  [FIRApp configure];

  // APPCENTER INITIALISATION
  [AppCenterReactNative register];
  [AppCenterReactNativeCrashes registerWithAutomaticProcessing];
  [AppCenterReactNativeAnalytics registerWithInitiallyEnabled:true];

  // GLOBAL EXCEPTION HANDLING
  [ReactNativeExceptionHandler replaceNativeExceptionHandlerBlock:^(NSException *exception, NSString *readeableException){

    // Replacement of default popup from react-native-exception-handler
    UIAlertController* alert = [UIAlertController
                                alertControllerWithTitle:@"Unexpected error occurred"
                                message: @"Please restart the app"
                                preferredStyle:UIAlertControllerStyleAlert];

    [rootViewController presentViewController:alert animated:YES completion:nil];

    // To close the app or to remove the UI lockup on exception.
    // method "[ReactNativeExceptionHandler releaseExceptionHold]"
    // should be called.
    // It is called with a timer with delay set to four seconds.
    [NSTimer scheduledTimerWithTimeInterval:4.0
                                     target:[ReactNativeExceptionHandler class]
                                   selector:@selector(releaseExceptionHold)
                                   userInfo:nil
                                    repeats:NO];
  }];

  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  // Needed for codepush feature
  return [CodePush bundleURL];
#endif
}

// DEEP LINKING HANDLING
- (BOOL)application:(UIApplication *)application
    openURL:(nonnull NSURL *)url
    options:(nonnull NSDictionary<NSString *,id> *)options
{
  BOOL handledFB = [[FBSDKApplicationDelegate sharedInstance] application:application
    openURL:url
    options:options
  ];

  BOOL handledGoogle = [RNGoogleSignin application:application
      openURL:url
      options:options
    ];

  BOOL handledRCT = [RCTLinkingManager application:application
    openURL:url
    options:options
  ];

  return handledFB || handledGoogle || handledRCT ;
}

@end


Android

Click To Expand

#### Have you converted to AndroidX? - [ ] my application is an AndroidX application? - [ ] I am using `android/gradle.settings` `jetifier=true` for Android compatibility? - [ ] I am using the NPM package `jetifier` for react-native compatibility? #### `android/build.gradle`:

// N/A
#### `android/app/build.gradle`:
// N/A
#### `android/settings.gradle`:
// N/A
#### `MainApplication.java`:
// N/A
#### `AndroidManifest.xml`:
<!-- N/A -->


Environment

Click To Expand

**`react-native info` output:**

 System:
    OS: macOS 10.15.2
    CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
    Memory: 1.42 GB / 16.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 8.16.2 - /usr/local/bin/node
    Yarn: 1.19.2 - /usr/local/bin/yarn
    npm: 6.4.1 - /usr/local/bin/npm
  SDKs:
    iOS SDK:
      Platforms: iOS 12.1, macOS 10.14, tvOS 12.1, watchOS 5.1
    Android SDK:
      API Levels: 23, 24, 25, 26, 27, 28, 29
      Build Tools: 27.0.3, 28.0.3, 29.0.2
      System Images: android-26 | Google APIs Intel x86 Atom, android-27 | Intel x86 Atom_64, android-27 | Google APIs Intel x86 Atom
  IDEs:
    Android Studio: 3.5 AI-191.8026.42.35.5977832
    Xcode: 10.1/10B61 - /usr/bin/xcodebuild
  npmPackages:
    react: 16.9.0 => 16.9.0 
    react-native: 0.61.5 => 0.61.5
- **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:** - `e.g. 6.2.0 and 6.1.0` - **`Firebase` module(s) you're using that has the issue:** - `e.g. dynamic-links` - **Are you using `TypeScript`?** - `N`




Think react-native-firebase is great? Please consider supporting all of the project maintainers and contributors by donating via our Open Collective where all contributors can submit expenses. [Learn More]

Most helpful comment

In order for your application to receive dynamic links when the application is running, you need to register continueUserActivity restorationHandler.

Check your ios/AppDelegate.m file does it have the following entry:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler { return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; }

Also, there is detailed documentation on React Native website regarding dynamic linking: https://facebook.github.io/react-native/docs/linking

All 3 comments

In order for your application to receive dynamic links when the application is running, you need to register continueUserActivity restorationHandler.

Check your ios/AppDelegate.m file does it have the following entry:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler { return [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; }

Also, there is detailed documentation on React Native website regarding dynamic linking: https://facebook.github.io/react-native/docs/linking

Thank you @abjelosevic88 , that was the issue! I removed that part of the code during the react native and this package update and didn't notice this mistake.

+10 internet points for @abjelosevic88 :trophy: :smile:

Was this page helpful?
0 / 5 - 0 ratings