eNeF
eNeF

Reputation: 3280

Firebase DeepLink does not work on Killed/Terminated App state in iOS14

I have integrated the Firebase DeepLink/DynamicLinks/UniversalLink into our app. When the app is running or in background/foreground state, Deep Links works with no problem. However, when the app is not running or in killed/terminated state the app will launch, but no trigger method will be called or initialize. It's like it only triggers the URL Scheme. So, as a result, I am not able to get the data on the deep links that were clicked, and that was the big problem.

In didFinishLaunchingWithOptions: launchOptions is always nil, and therefore launchOptions[.url] is nil

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool

And open url:options: does not trigger

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool

And ofcourse this one continue userActivity:restorationHandler: does not trigger

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool

So, I was only able to launch the app with no data captured. Any workaround or suggestion is appreciated. Thanks!

Upvotes: 1

Views: 2627

Answers (1)

eNeF
eNeF

Reputation: 3280

Took me sometime to resolve this issue. After trying a bunch of workaround, the solution that worked was to migrate to the new Apple's App Structure using SceneDelegate.

To handle DeepLink from terminated state, you need to configure this function:

var window: UIWindow?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    if let userActivity = connectionOptions.userActivities.first, let url = userActivity.webpageURL {            
        DynamicLinks.dynamicLinks().handleUniversalLink(url) { dynamicLink, error in
            guard let dynamicLink = dynamicLink, let url = dynamicLink.url else { return }
            parseDynamicLink(fromURL: url)
        }
    }
    
    guard let windowScene = (scene as? UIWindowScene) else { return }
    
    // Initialize UIWindow
    window = UIWindow(windowScene: windowScene)
    window?.rootViewController = YOUR_ROOT_VIEW_CONTROLLER
    window?.makeKeyAndVisible()
}

To handle the other part of the scene delegate which are UIApplication equivalent:

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
    guard let url = userActivity.webpageURL else { return }
    DynamicLinks.dynamicLinks().handleUniversalLink(url) { dynamicLink, error in
        guard let dynamicLink = dynamicLink, let url = dynamicLink.url else { return }
        parseDynamicLink(fromURL: url)
        
        // launch dynamic link code here...?
    }    
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let urlContext = URLContexts.first else { return }

    if let dynamicLink = DynamicLinks.dynamicLinks().dynamicLink(fromCustomSchemeURL: urlContext.url) {
        guard let url = dynamicLink.url else { return }
        parseDynamicLink(fromURL: url)
    }    
}

If you plan to do the migration, make sure to properly configure your Info.plist's Application Scene Manifest then set your scene configuration here:

func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

Your Application Scene Manifest should look something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>UIApplicationSupportsMultipleScenes</key>
        <false/>
        <key>UISceneConfigurations</key>
        <dict>
            <key>UIWindowSceneSessionRoleApplication</key>
            <array>
                <dict>
                    <key>UISceneDelegateClassName</key>
                    <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                    <key>UISceneStoryboardFile</key>
                    <string>Main</string>
                    <key>UISceneConfigurationName</key>
                    <string>Default Configuration</string>
                </dict>
            </array>
        </dict>
    </dict>
</plist>

Upvotes: 6

Related Questions