Linking url event never fires

This issue has been created since 2022-09-15.

Description

Url event never fires

I followed the indicated setup to handle deep links in react native.

But when I have the app open in background or foreground and I execute command
npx uri-scheme open "mychat://bar" --ios, url event doesn't fire.

I saw there is a similar issue in react-navigation, but the fix indicated for AppDelegate.m doesn't work for me.

Version

0.70

Output of npx react-native info

System:
OS: macOS 12.5.1
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 59.18 MB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.13.1 - /usr/local/opt/[email protected]/bin/node
Yarn: 1.22.11 - /usr/local/bin/yarn
npm: 8.1.2 - /usr/local/opt/[email protected]/bin/npm
Watchman: Not Found
Managers:
CocoaPods: 1.11.2 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5
Android SDK:
API Levels: 28, 31, 33
Build Tools: 30.0.2, 31.0.0, 33.0.0
System Images: android-31 | Google APIs Intel x86 Atom_64, android-31 | Google Play Intel x86 Atom_64
Android NDK: Not Found
IDEs:
Android Studio: 2021.2 AI-212.5712.43.2112.8815526
Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild
Languages:
Java: 13.0.2 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 18.1.0 => 18.1.0
react-native: 0.70.0 => 0.70.0
react-native-macos: Not Found
npmGlobalPackages:
react-native: Not Found

Steps to reproduce

clone repo https://github.com/leoparis89/deeplink

  1. yarn
  2. cd ios && pod install
  3. yarn ios
  4. run command npx uri-scheme open "mychat://bar" --ios.
    App gets focused but url event never fires in ./useDeepLink.js line 15.

Snack, code example, screenshot, or link to a repository

https://github.com/leoparis89/deeplink

ariel-bentu wrote this answer on 2022-09-20

I want to add to this issue what I researched, having similar issue:

  • When the app is not running at all, and you select "share/open with" your app the following happens:
    • First, the (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions is called, having the path to the file in the launch options under "UIApplicationLaunchOptionsURLKey" key.
      This path is not accessible (permission-wise to the app).
      This path is also what you'd get if you call Linking.getInitialURL
    • Then, the (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:... is called.
      This method receives a different URL, which is a copy of the file in your app's temp/inbox folder - fully accessible to your app.
      And as suggested, it is implemented with one line: return [RCTLinkingManager application:application openURL:url options:options];, which triggers RCTLinkingManager to send notification via NSNotificationCenter with that (good) url.
      Now comes the issue: at this point in time, the JS was not yet started and the JS part of the app did not register to listen to "url" event. That is why RCTEventEmitter did not call RCTLinkingManager.startObserving and the notification with the url is lost. and even if it would have been received, the JS did not register yet, and it would not have been fired to the JS part.

Here is how I solved it (and I suggest you implement something more generic/robust for Linking:

  • when RCTLinkingManager application:application openURL:url options:options is called, I save the url in a object's local variable. the when RCTLinkingManager.startObserving is called, if this variable is not nil, I fire the url event.

  • line 19: static NSString *savedEvent = nil;
    at startObserving, at its end:

if (savedEvent != nil) {
        NSDictionary<NSString *, id> *payload = @{@"url": savedEvent};
        [self sendEventWithName:@"url" body:payload];
        savedEvent = nil;
    }

at application:openURL:options

    // if event was missed, save it for later firing
    savedEvent = URL.absoluteString;

I hope this helps.

leoparis89 wrote this answer on 2022-09-21

I want to add to this issue what I researched, having similar issue:

  • When the app is not running at all, and you select "share/open with" your app the following happens:

    • First, the (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions is called, having the path to the file in the launch options under "UIApplicationLaunchOptionsURLKey" key.
      This path is not accessible (permission-wise to the app).
      This path is also what you'd get if you call Linking.getInitialURL
    • Then, the (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:... is called.
      This method receives a different URL, which is a copy of the file in your app's temp/inbox folder - fully accessible to your app.
      And as suggested, it is implemented with one line: return [RCTLinkingManager application:application openURL:url options:options];, which triggers RCTLinkingManager to send notification via NSNotificationCenter with that (good) url.
      Now comes the issue: at this point in time, the JS was not yet started and the JS part of the app did not register to listen to "url" event. That is why RCTEventEmitter did not call RCTLinkingManager.startObserving and the notification with the url is lost. and even if it would have been received, the JS did not register yet, and it would not have been fired to the JS part.

Here is how I solved it (and I suggest you implement something more generic/robust for Linking:

  • when RCTLinkingManager application:application openURL:url options:options is called, I save the url in a object's local variable. the when RCTLinkingManager.startObserving is called, if this variable is not nil, I fire the url event.
  • line 19: static NSString *savedEvent = nil;
    at startObserving, at its end:
if (savedEvent != nil) {
        NSDictionary<NSString *, id> *payload = @{@"url": savedEvent};
        [self sendEventWithName:@"url" body:payload];
        savedEvent = nil;
    }

at application:openURL:options

    // if event was missed, save it for later firing
    savedEvent = URL.absoluteString;

I hope this helps.

Could you specify in which file those modifications need to be made ?
Ideally could you also post a snippet of the modified code ?

Haven't been able to reproduce your instructions.
Thanks

ariel-bentu wrote this answer on 2022-09-22

The file is react-native/Libraries/LinkingIOS/RCTLinkingManager.mm

#import <React/RCTLinkingManager.h>

#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTUtils.h>
#import <React/RCTLog.h>

#import "RCTLinkingPlugins.h"

static NSString *const kOpenURLNotification = @"RCTOpenURLNotification";

static NSString *savedEvent = nil;
- (void)startObserving
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleOpenURLNotification:)
                                                 name:kOpenURLNotification
                                               object:nil];
    if (savedEvent != nil) {
        NSDictionary<NSString *, id> *payload = @{@"url": savedEvent};
        [self sendEventWithName:@"url" body:payload];
        savedEvent = nil;
    }
}
+ (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)URL
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
    postNotificationWithURL(URL, self);
    
    // if event was missed, save for firing later if event "url" is registered
    savedEvent = URL.absoluteString;
    
    return YES;
}
edwardhsueh wrote this answer on 2022-09-22

@ariel-bentu
I try you solution , but url event doesn't fire when I have the app open in background or foreground.
(when app closed , it's ok).
Do you have any suggestion ?

ariel-bentu wrote this answer on 2022-09-22

do you have this method added in your AppDelegate.mm:

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

This is a prerequisite, also documented by react native (see here)

edwardhsueh wrote this answer on 2022-09-23

Yes, I do follow the document but still fail. I can't run in simulator, so I use browser with button to call the url scheme.
if app is closed, it works fine. But if app is in background, the url scheme called just bring app to foreground, but the url listener is not fired.
My RN is 0.68.2, older than yours. Will this be a problem?
By the way, can your app receive url event when it is in background?

More Details About Repo
Owner Name facebook
Repo Name react-native
Full Name facebook/react-native
Language JavaScript
Created Date 2015-01-09
Updated Date 2022-10-07
Star Count 105180
Watcher Count 3671
Fork Count 22481
Issue Count 2230

YOU MAY BE INTERESTED

Issue Title Created Date Comment Count Updated Date
No FDM-8000_corndog.stl in v2.1.4 3 2022-06-16 2022-07-16
impl PartialEq for reqwasm::http::Method 2 2021-12-25 2022-08-20
Webpack issues on M1 Mac Book Pro 4 2021-11-08 2022-09-24
Release version for angular >= 12 2 2021-08-12 2022-09-16
0.2.3c support for Blender 3.X(or optional 20tab integration for the recent builds) 4 2022-04-23 2022-09-22
PEP 592 support not released? 2 2020-09-16 2022-09-24
Virus Total flags have changed since last version. 2 2022-04-28 2022-09-10
Custom windows 10 themes have trouble seeing text 1 2022-01-04 2022-09-10
about the classification method's output interval's precision 1 2021-01-31 2022-09-22
padlocal版本是否支持@所有人和发送一段固定的微信语音 3 2022-06-10 2022-09-23
Not able to create aws eks cluster 2 2022-04-06 2022-09-28
Forward .well-known of gitlab to docker image 1 2022-06-02 2022-09-28
Is the library Synchronous or Asynchronous 0 2021-03-05 2022-09-07
std::uncaught_exceptions is only available if compiling for macOS 10.12 or above 1 2021-02-04 2022-10-02
Improve callback function support 2 2021-12-30 2022-09-18
The list of applications disappears when the Realtek settings are changed 4 2021-08-22 2022-08-06
`Window.prompt` should distinguish between empty Ok and Cancel 0 2022-04-10 2022-09-16
Digital Certificate 5 2021-11-26 2021-12-27
CefSettings 5 2021-12-09 2021-12-27
Pandomium is not initialized yet 6 2021-12-21 2022-09-17
HACS There are 1 updates to HACS components at 03:52: 0 2022-07-21 2022-09-24
Uname process doesn't close when running in Linux OS 4 2022-01-02 2022-09-22
Admin: allow resetting instructor registration key 0 2021-09-19 2022-09-13
bug: Fix dependency version 0 2022-07-17 2022-10-01
GRIN General fund page outdated 1 2021-02-25 2022-09-29
Crash on launch [WSL] 1 2021-09-22 2022-10-02
Stop shipping with StableRNGs? 3 2021-10-05 2022-09-27
No version for Julia 1.6.1 1 2021-10-04 2022-09-27
React-todo example setup issues 0 2021-11-29 2022-09-25
PowerShell script to be changed 0 2022-09-14 2022-09-30
Next release WhereYouGo 1 2022-01-15 2022-09-30
Remove intersecting regions in the region cache when updating regions 0 2022-08-16 2022-09-19
'cf delete-user' with CF7 fails if user does not exist in ccdb 4 2020-10-20 2022-09-16
Need to deprecate or remove Syntax::replaceActionSyntax 0 2022-01-08 2022-01-22
"saveState", "loadStateState" in "Change Simulation St" 3 2021-12-14 2022-10-05
Error: No results to report 1 2020-01-06 2022-10-04
感谢老铁们的无私贡献,目前发现三个版本的Flutter版WeUI了 0 2019-12-16 2022-10-02
Showcase "transfer learning" with imagenet example 1 2021-09-24 2022-09-24
Upgrade to Tailwind 3 0 2021-02-11 2022-09-28
Amdroid Version Support 1 2021-02-24 2022-09-26
Add multiple Broadlink LBs 4 2022-01-04 2022-09-03
Gravação de tela e aúdio 1 2021-11-03 2022-09-24
Define encoding of "password" to UTF-8 5 2020-11-28 2022-09-28
Provide arm64 version of docker images 3 2022-05-11 2022-09-22
Boundary provider needs assume_role 15 2021-01-08 2022-10-06
Support insecure tls 4 2021-02-12 2022-10-06
[Improvement] `AlterViewAsCommand` should be skipped permission check 0 2022-09-06 2022-10-05
bug: the destroy function of plugin cant be called 1 2022-03-06 2022-08-01
Add `cast` expressions in `ast::Expr` 0 2022-02-10 2022-09-18
[Bug Report][3.0.0-beta.3] <v-text-field /> not add class that `v-input--error` when validate with 3rd party plugin 0 2022-06-04 2022-10-07