Search code examples
javascriptiosreact-nativereact-native-iosfirebase-dynamic-links

Dynamic link through scan QR code open the app then won't navigate to different screen


My App which created using React Native require functionality to scan QR code with default camera app then open specific screen in the app, in order to achieve this I setup Firebase dynamic links by also using React Native Firebase library.

The setup were pretty simple, a dynamic link using Firebase provided domain, the link also contain deep link in url format https://example.page.link/abc-xyz.

After the app scan the QR it use deep link url to extract the abc-xyz part and navigate to different screen, here is my implementation.

// App.js
const handleDynamicLink = link => {
  const linkCheck = new RegExp('^https://example.page.link/.*$');
  let title;

  if (linkCheck.test(link.url)) {
    title = link.url.substring(link.url.lastIndexOf('/') + 1).split('-');

    RootNavigation.navigate(Screens.offer, { title: title });
  }
};

...

React.useEffect(() => {
  // Handler for background/quit events
  dynamicLinks().getInitialLink().then(link => {
    handleDynamicLink(link);
  });
  
  // Handler for foreground events
  const unsubscribe = dynamicLinks().onLink(handleDynamicLink);
  return () => unsubscribe();
}, []);

// RootNavigation.js
import * as React from 'react';

export const navigationRef = React.createRef();

export function navigate(name, params) {
  navigationRef.current?.navigate(name, params);
}

All necessary setup already configured both for iOS and Android, doing test with Android device by scanning the QR code, it recognise the link and navigate to intended screen, but not for iOS even though it understand the link and it only open the initial screen then stop there.

Strange thing is if I open the link directly in device browser it will open the preview page, then if I click the "open" button it open the app and navigate to target screen.

Wondering is this has something to do with navigation stuff in the iOS native side?


Solution

  • Turns out I need to update AppDelegate.m and add link handler for iOS.

    Added below code above @end line in AppDelegate.m.

    // AppDelegate.m
    
    - (BOOL)application:(UIApplication *)application
       openURL:(NSURL *)url
       options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
    {
      return [RCTLinkingManager application:application openURL:url options:options];
    }
    
    - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
     restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
    {
     return [RCTLinkingManager application:application
                      continueUserActivity:userActivity
                        restorationHandler:restorationHandler];
    }
    

    Handling when app in foreground state or already open.

    // App.js
    
    if (Platform.OS === 'ios') {
      Linking.addEventListener('url', handleDynamicLink);
    }
    

    Handling when app is fully closed/initiated by dynamic link.

    // App.js
    
    if (Platform.OS === 'ios') {
      Linking.getInitialURL()
        .then(link => {
          handleDynamicLink({ url: link });
        })
        .catch(error => {
          // Error handling
        });
    } else {
      // This part for Android
      dynamicLinks().getInitialLink().then(link => {
        handleDynamicLink(link);
      });
    }