Home > front end >  Flutter IOS Universal Link Opens App, But Does Not Navigate To Correct Page
Flutter IOS Universal Link Opens App, But Does Not Navigate To Correct Page

Time:01-26

I have set up Universal Links on my flutter project for IOS.

Like the title suggests, my app does open when I click on a link relating to my site but it does not navigate to the correct page. It just opens the app. I'm not using the uni_links package, rather I used a combination of guides (including official documentation):

https://developer.apple.com/videos/play/wwdc2019/717/

https://nishbhasin.medium.com/apple-universal-link-setup-in-ios-131a508b45d1

https://www.kodeco.com/6080-universal-links-make-the-connection

I have setup my apple-app-site-association file to look like:

{
    "applinks": {
        "details": [
            {
                "appIDs": [
                    "XXXXXXX.com.my.appBundle"
                ],
                "componenents": [
                    {
                        "/": "/*"
                    }
                ]
            }
        ]
    }
}

and I have added this to my info.plist file:

<key>FlutterDeepLinkingEnabled</key>
<true/>

and my AppDelegate.swift file looks like:

import UIKit
import Flutter
import Firebase

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(_ application: UIApplication, continue userActivity: NSUserActivity, 
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // This will allow us to check if we are coming from a universal link
    // and get the url with its components
    // The activity type (NSUserActivityTypeBrowsingWeb) is used
    // when continuing from a web browsing session to either
    // a web browser or a native app. Only activities of this
    // type can be continued from a web browser to a native app.
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
      let url = userActivity.webpageURL,
      let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
        return false
    }
    // Now that we have the url and its components,
    // we can use this information to present
    // appropriate content in the app
    return true
  }

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    FirebaseApp.configure()
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

My Runner-entitlements are also setup correctly like:

<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:www.example.com</string>
    <string>applinks:*.example.com</string>
</array>

The issue is, if I click a hyperlink for www.example.com/mypath , it does not got to the page/route handled by /mypath, but instead just opens the app.

My routing is done using go_router: ^5.2.4

Please does anyone know why this is happening? I'm blocked by this. I have seen similar questions, but none with answers that have worked for me. Any help is appreciated.

CodePudding user response:

When you handle the dynamic link you get the universal link and other data in the userActivity parameter of the following function.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    if let incomingURL = userActivity.webpageURL {
        debugPrint("incoming url is", incomingURL)
        let link = DynamicLinks.dynamicLinks().shouldHandleDynamicLink(fromCustomSchemeURL: incomingURL)
        print(link)
        let linkHandle = DynamicLinks.dynamicLinks().handleUniversalLink(incomingURL) { link, error in
            guard error == nil else {
                print("Error found.")
                return
            }
            if let dynamicLink = link {
                self.handleDynamicLinks(dynamicLink)
            }
        }
        if linkHandle {
            return true
        } else {
            return false
        }
    }
    return false
}

Parse the data from another function or you can parse in above code also. In my case I parsed the code in below function.

func handleDynamicLinks(_ dynamicLink: DynamicLink) {
    guard let link = dynamicLink.url else {
        return
    }
    
    if let landingVC = self.window?.rootViewController as? LandingViewController {
       // Do you your handling here with any controller you want to send or anything.
    }
          // example you are getting ID, you can parse it here

    if let idString = link.valueOf("id"), let id = Int.init(idString) {
        print(id)
    }
}

When you get the details from the link you can simply fetch the navigation controller or the VisibleController, and then can push to the desired flow.

CodePudding user response:

Ok so figured it out [Debug Mode]. The official apple documentation requests the addition of a variation of this function in the AppDelegate.swift file:

func application(_ application: UIApplication, continue userActivity: NSUserActivity, 
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // This will allow us to check if we are coming from a universal link
    // and get the url with its components
    // The activity type (NSUserActivityTypeBrowsingWeb) is used
    // when continuing from a web browsing session to either
    // a web browser or a native app. Only activities of this
    // type can be continued from a web browser to a native app.
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
      let url = userActivity.webpageURL,
      let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
        return false
    }
    // Now that we have the url and its components,
    // we can use this information to present
    // appropriate content in the app
    return true
  }

Seems that it conflicts with the flutter framework for handling universal links. Taking that function out and just having this in my info.plist worked (everything else stayed the same):

<key>FlutterDeepLinkingEnabled</key>
<true/>
  • Related