How to iOS Universal Links for a Seamless App User Experience

View: 2787    Dowload: 0   Comment: 0   Post by: hanhga   Category: iPhone OS   Fields: Other

Server Setup :

The server app will be a simple Rails app that displays a list of authors and some of their books. The easiest way for you to get started is to clone the app on Heroku, just click the button below.If you don’t want to take this option, you can also deploy the app yourself by cloning the app on Github and push it to a host of your choice.

You can see the app in action here. By default, it shows a list of authors. Clicking on any author displays a list of books written by them.

The App-Site-Association File

Just having a server running online isn’t enough. To securely associate your iOS app with a server, Apple requires that you make available a configuration file, called apple-app-site-association. This is a JSON file which describes the domain and supported routes.

The apple-app-site-association file needs to be accessible via HTTPS, without any redirects, athttps://{domain}/apple-app-site-association.

   "applinks": {
       "apps": [ ],
       "details": [
               "appID": "{app_prefix}.{app_identifier}",
               "paths": [ "/path/to/content", "/path/to/other/*", "NOT /path/to/exclude" ]

The keys are as follows:

  • apps: Should have an empty array as its value, and it must be present. This is how Apple wants it.
  • details: Is an array of dictionaries, one for each iOS app supported by the website. Each dictionary contains information about the app, the team and bundle IDs. In the example app, it’ and the paths supported by the app.
  • {
    "applinks": {
      "apps": [],
      "details": [
          "appID": "",
          "paths": [

    There are 3 ways to define paths:

  • Static: The entire supported path is hardcoded to identify a specific link, e.g. /static/terms
  • Wildcards: A * can be used to match dynamic paths, e.g. /authors/* can matches the path to any author’s page. ? inside specific path components, e.g. authors/1? can be used to match any authors whose ID starts with 1.
  • Exclusions: Prepending a path with NOT excludes that path from being matched.
  • The order in which the paths are mentioned in the array is important. Earlier indices have higher priority. Once a path matches, the evaluation stops, and other paths ignored. Each path is case-sensitive.

    Supporting Multiple Domains

    Each domain supported in the app needs to make available its own apple-app-site-association file. If the content served by each domain is different, then the contents of the file will also change to support the respective paths. Otherwise, the same file can be used, but it needs to be accessible at every supported domain.

    Note: This means that if you need both and supported in your app, the association file should be accessible at both these domains.

    Signing the App-Site-Association File

    If your app targets iOS 9 and your server uses HTTPS to serve content, you don’t need to sign the file. If not (e.g. when supporting Handoff on iOS 8), it has to be signed using a SSL certificate from a recognized certificate authority.

    Note: This is not the certificate provided by Apple to submit your app to the App Store. It should be provided by a third-party, and it’s recommended to use the same certificate you use for your HTTPS server (although it’s not required).

    To sign the file, first create and save a simple .txt version of it. Next, in the terminal, run the following command:

  • cat <unsigned_file>.txt | openssl smime -sign -inkey -signer -certfile intermediate.pem -noattr -nodetach -outform DER > apple-app-site-association

    This will output the signed file in the current directory. The, andintermediate.pem are the files that would made available to you by your Certifying Authority.

  • App Setup

    Next is the app, that mirrors the server. It will target iOS 9 and will be using Xcode 7.2 with Swift 2.1.

    The app will talk to the server and display the following:

  • The list of authors: Calling /authors.json on the server will get you the data.
  • The profile of an author: Called when an author is tapped. The endpoint in this case is/authors/:id.json.
  • The list of books of an author: Available from /authors/:id/books.json.
  • The app code can be found on Github.

    This is how the app looks:

    App Screenshot 1

    App Screenshot 2

    App Screenshot 3

    Important – Changes Required

    If you intend to create your own instance of the sample server and clone the iOS sample app, make the following changes:

  • Change the bundle ID to something that will be used in your app ID in the Member Center.
  • The team should be the one associated with your developer account.
  • kBaseURL in AppDelegate.swift should point to your instance of the web server.
  • Update /public/association.json on the Rails app with your App ID prefix and suffix.
  • Changes required

    Enabling Universal Links

    The setup on the app side requires two things:

  • Configuring the app’s entitlement, and enabling universal links.
  • Handling Incoming Links in your AppDelegate.
  • Entitlements

    Note: Ensure you have selected the same team and entered the same Bundle ID as the registered App ID on the Member Center. Also ensure that the entitlements file is included by Xcode by selecting the file and in the File Inspector, ensure that your target is checked.

    App Target Membership

    Handling incoming links

    application:continueUserActivity:restorationHandler: in the UIApplicationDelegatemethod in AppDelegate.swift handles incoming links. The method gives an NSUserActivity object, with an activityType value of NSUserActivityTypeBrowsingWeb and a webpageURL property containing the URL. You parse this URL to determine the right action in the app.

    For example, in the sample app:

    Configuring Entitlements

    The first step in configuring your app’s entitlements is to enable it for your App ID. Do this in the Apple Developer Member Center.

    Click on Certificates, Identifiers & Profiles and then Identifiers. Select your App ID (create it first if required), click Edit and enable the Associated Domains entitlement.

    App ID Creation

    Next, get the App ID prefix and suffix by clicking on the respective App ID.

    App ID Prefix

    The App ID prefix and suffix should match the one in the apple-app-site-association file.

    Next in Xcode, select your App’s target, click Capabilities and toggle Associated Domains to On. Add an entry for each domain that your app supports, prefixed with applinks:.

    For and

    Which looks like this for the sample app:

  • let router = SHNUrlRouter()
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
          return true
      func bindRoutes(){
        // Register routes that're handled
          let storyboard = UIStoryboard(name: "Main", bundle: nil)
          let root = self.window?.rootViewController as! UINavigationController
          router.register("/authors") { (params) -> Void in
              let list: AuthorsTableViewController = storyboard.instantiateViewControllerWithIdentifier("AuthorsTableViewController") as! AuthorsTableViewController
              root.pushViewController(list, animated: true)
          router.register("/authors/{id}") { (params) -> Void in
              let profileVC: AuthorProfileViewController = storyboard.instantiateViewControllerWithIdentifier("AuthorProfileViewController") as! AuthorProfileViewController
              profileVC.authorID = Int(params["id"]!)
              root.pushViewController(profileVC, animated: true)
          router.register("/authors/{id}/books") { (params) -> Void in
              let list: BooksTableViewController = storyboard.instantiateViewControllerWithIdentifier("BooksTableViewController") as! BooksTableViewController
              list.authorID = Int(params["id"]!)
              root.pushViewController(list, animated: true)
      func application(application: UIApplication, continueUserActivity userActivity: NSUserActivity, restorationHandler: ([AnyObject]?) -> Void) -> Bool {
          if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
              let url = userActivity.webpageURL!
          return true

    The SHNURLRouter library matches the incoming links and takes the appropriate action.

    Testing Universal Links

    If you have your own server instance running and associated with your app, you can now test Universal Links.

    Generally, any supported link clicked in Safari, or in instances of UIWebView/WKWebView should open the app. A good testing source is the read me of a Github repo. You can fork and edit any of the sample apps in this article.

    If you don’t have your own server or just want to see this in action, click the links in the read me here.

How to iOS Universal Links for a Seamless App User Experience

The server app will be a simple Rails app that displays a list of authors and some of their books.

Posted on 22-02-2016 


To comment you must be logged in members.

Files with category

File suggestion for you
File top downloads
Codetitle - library source code to share, download the file to the community
Copyright © 2018. All rights reserved. codetitle Develope by Vinagon .Ltd