Legolas
Legolas

Reputation: 12325

iOS Universal Links are not opening in-app

So I followed this tutorial exactly and use the same values as the ones provided: https://blog.branch.io/how-to-setup-universal-links-to-deep-link-on-apple-ios-9

The Apple Association file is also ready in the link directory:
WEB_PAGE:PORT_NUMBER/apple-app-site-association

Everything seems to be set up on this side.

I've added the entitlements, updated the provisioning profile, and everything's set up.

When I run the app on my device, and open the link http://WEB_PAGE:PORT_NUMBER, this always opens Safari.

I even have breakpoints in the following method:

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler

But zilch.

Has anyone perfected this? Is there something I'm missing?

Upvotes: 159

Views: 183149

Answers (30)

st.derrick
st.derrick

Reputation: 4919

There are a few possible issues.

  1. Try pasting your domain into this link validator and make sure there are no issues: https://branch.io/resources/aasa-validator/ (credit to ShortStuffSushi -- see repo)

  2. iOS logs an error message in the system logs if you don't have TLS set up properly on the domain specified in your entitlements. It's buried in the OS logs, not application logs. The error message will look like Sep 21 14:27:01 Derricks-iPhone swcd[2044] <Notice>: 2015-09-21 02:27:01.878907 PM [SWC] ### Rejecting URL 'https://examplecustomdomain.com/apple-app-site-association' for auth method 'NSURLAuthenticationMethodServerTrust': -6754/0xFFFFE59E kAuthenticationErr. Error message pulled from here, quick (incomplete) instructions on using CloudFlare for TLS here.

  3. In my personal testing, clicking/typing in a link in Safari has never once opened the app directly. Clicking from other apps (iMessage, Mail, Slack, etc.) has worked. Others have reported that clicking links in Google search results have opened the app directly.

  4. Note that if a Universal Link succeeds in opening your app and then you click through to Safari (by tapping your site in the top right corner of the nav bar in app), then iOS stops opening the app when you visit that URL. Then in Safari, you can pull down to reveal a banner at the top of the page with "Open". I wasted a lot of time on this. Note that clicking through to the site => disabling UL seems path specific, based on the paths you specify in the apple-app-site-assocation file. So if you have separate routes, yoursite.com/a/* and yoursite.com/b/*, if you click yoursite.com/a/* and it opens your app directly, you then have the option in the top right corner of the app to click through to yoursite.com/a/*. If you do that, subsequent visits to yoursite.com/a/* will open in browser, not app. However, yoursite.com/b/* should be unaffected and still open your app directly.

Let me know if you discover what the issue is. I'm personally very curious about how Universal Links work and what edge cases exist.

Upvotes: 226

rotoxl
rotoxl

Reputation: 159

Its 2024 and still struggling with this, in my case the apple-app-site-association was behind a VPN, so it had increased difficulty.

There's a iOS tool that might be handy. In your iOS device go to Settings / Developer and look for a section called UNIVERSAL LINKS, then check the diagnostics tool in which you can test the universal link

Universal links diagnostic tool

Upvotes: 0

Devy
Devy

Reputation: 10179

To validate apple-app-site-association on the server side, you can use this online validator.

https://branch.io/resources/aasa-validator/

Upvotes: 32

Naresh
Naresh

Reputation: 955

Sometimes the apple-app-site-association is not accessible to the cdn.apple.come. I was facing that issue. After so many R&D I got to know that we can check that.

Suppose your universal link is - https://ios.with.naresh.com/universallinkdemo

Domain name -- ios.with.naresh.com

So if your apple-app-site-association is not accessible at

https://app-site-association.cdn-apple.com/a/v1/ios.with.naresh.com

that mean there is some issue at backend. The apple cdn is not able to access the file content. This generally happens because of some access issue at backend side.

You can get more info of this if you hit this URL in postman or by inspecting the browser tab. If you are seeing the status code except 200 then there is some issue at backend from mobile side you can't do anything. You may connect with your team.

Upvotes: 0

Claytog
Claytog

Reputation: 957

If you've tried everything mentioned above, and links in emails etc, are still not opening your app (and you are using a real device and not the simulator), ensure that you are not just using the app deployed to your device via XCode, and are using an app that is at least deployed to your device via TestFlight.

Upvotes: 0

JAHelia
JAHelia

Reputation: 7902

for my case it was because I didn't enable the Association Domain Development in Developer menu in iOS Settings on the device. and it doesn't work on simulator

Upvotes: -1

user3673952
user3673952

Reputation: 967

I have found 2 useful tools that you can use to debug issues with Universal Links:

  1. On your phone, open the Settings app, select the Developer menu -> enable Association Domain Development and select Diagnostics. Insert the url that you have added to your entitlements file, and it will be validated: enter image description here

  2. The second one is mentioned in Apple's TN3155: Debugging universal links article. I recommend you read the full article, but especially the Host and verify your AASA chapter.

The mention using swcutil to verify your AASA files:

You can use these commands in Terminal by:

Running sudo swcutil dl -d <domain> to check that the AASA JSON can be downloaded successfully.

Running sudo swcutil verify -d <domain> -j <path-to-JSON> [-u <URL>] to check the contents of a downloaded .json AASA file. Verify that your domains match with -d and your URL path pattern matches with the JSON with -u. If both are successful, you will get a confirmation message.

For an app containing applinks:example.com and the AASA shown above, here is an example of using swcutil verify where “s” is the service, “a” is the App ID, and “d” is the domain:

% sudo swcutil verify -d example.com -j ./example.json -u https://example.com/test
{ s = applinks, a = ABCD123.com.example.app, d = example.com }:
Pattern "https://example.com/test" matched.

Since the pattern /test is included in the AASA, the JSON has successfully pattern matched and is verified. For the path /path/1, since it is set to be excluded in the AASA, you would see a message confirming the exclusion:

Pattern "https://example.com/path/1" blocked match.

Upvotes: 15

Eel
Eel

Reputation: 1449

To validate apple-app-site-association file you can use this tool:

https://branch.io/resources/aasa-validator/#resultsbox

If you using something like cloudflare, make sure you didn't block countries in security rules

there are some countries that you should not block in order for app links to word

If you still have the error, go to apple developer account to where you register your app identifier, uncheck Associated websites and recheck it and then click save, open your project at xcode and disable auto manage signing and re enable it and choose your developer team, make sure the Association Domains capsbility and confirm the app links:example.com

if the issue still exists, make sure the apple-app-site-association route/file don't have content-type and try again, and if still have the issue, try out application/json

every time you try, delete the app and try build with different build number, try on different devices/simualtor, restart your router, your devices, try look at the console app in your Mac, you also might want to try use manual signing, allow any kind of links in apple-app-site-association just to make debugging easier

also try to use this command to test the link instead of open it in safari:

xcrun simctl openurl booted https://example.com

Upvotes: 1

David Miguel
David Miguel

Reputation: 14360

In my case the encoding of the file was incorrect.

Make sure you encode the file using UTF-8 and that you specify it in the Content-Type header:

Content-Type: application/json; charset=utf-8

You can easily verify it by pasting your URL on this site:

Invalid encoding Valid encoding

Upvotes: 3

Kiran Jadhav
Kiran Jadhav

Reputation: 3317

**One Simple thing need to check: **

Open Xcode & go to singing & capabilities section -

  1. Uncheck Automatically manage singing

  2. Create development certificate (If not created with same team id)

  3. Create development provisioning profile

NOTE : TEAM ID MUST SAME AS YOU MENTION in apple app site association file (aasa file)

simple uninstall previous app and run project again then open safari browser on simulator or device -> it will work...!

It help me find out solution because I run my project using automatically manage singing (checkbox is tick)

enter image description here

Upvotes: 2

Kylan Hurt
Kylan Hurt

Reputation: 23

I know there are already a lot of answers but you need to make sure that, in addition to the Developer Console (Apple's website), you also need to add the Associated Domains capability to the app via xCode. I had never done this process before and there isn't much documentation on it (including React Native's docs).

(Screen recording of the process below). https://i.sstatic.net/A7B1l.jpg

Upvotes: 0

Ste Prescott
Ste Prescott

Reputation: 1817

Sometimes I find that everything is fine with the association file but iOS decides to always open the universal link in Safari. To test if the app recognises the app link I add the URL to Notes or a Calendar entry and then long press it so the contextual menu appears. If it says "Open in {YOUR APP}" then the link is working but iOS is deciding to open it in Safari. Tapping "Open in {YOUR APP}" will tell iOS to open valid universal links via your app from then on.

Upvotes: 6

Sagar Sukode
Sagar Sukode

Reputation: 1371

There is a new format for file - check this link: https://developer.apple.com/documentation/safariservices/supporting_associated_domains_in_your_app?language=objc

I updated my file like this:

"applinks": {
        "apps": [],
        "details": [
            {
                "appID": "APP_ID_PREFIX.BUNDLE_ID",
                "paths": [
                    "*"
                ]
            }
        ]
    },
    "webcredentials": {
        "apps": [
            "APP_ID_PREFIX.BUNDLE_ID"
        ]
    }
}

Note: In simulator it`s not working but, on device working perfectly.

Upvotes: 1

Nikolay Suvandzhiev
Nikolay Suvandzhiev

Reputation: 9055

In my case I needed to make the server serve the apple-app-site-association file using content type: application/pkcs7-mime. In nginx I did it using this approach:

location ~ /.well-known/apple-app-site-association {
         default_type application/pkcs7-mime;
 }

As other suggested I also had to make sure I:

Note that I never saw the "success" messages in the Console app as shown in screenshots by another user. In the console I kept getting Entry [...] needs its JSON updated because the app PI changed, but this was not an issue.

Also note that when trying to open the apple-app-site-association in the browser, the file gets downloaded instead of displayed, but this was not an issue in my case.

And as always, use a real device, re-install app whenever you change things, potentially also restart device and maybe increment app version number.

Upvotes: 3

Jakub S.
Jakub S.

Reputation: 6080

In my cas it was not woking because I had 2 items in

<plist version="1.0">
<dict>
    <key>aps-environment</key>
    <string>development</string>
    <key>com.apple.developer.associated-domains</key>
    <array>
        <string>applinks:urlOne</string>
        <string>applinks:urlTwo</string>
    </array>
</dict>
</plist>

when I reduce array to only one item it start to work.

Upvotes: 2

Anita
Anita

Reputation: 3146

For ios13, there is a new format - check out here https://developer.apple.com/documentation/safariservices/supporting_associated_domains_in_your_app?language=objc

I updated my file to look like this:

 {
  "applinks": {
    "apps": [],
    "details": [
        {
          "appIDs": ["1234.app.company.appname"],
          "appID": "1234.app.company.appname",
          "components": [
            {
              "/": "/login"
            }
         ],
           "paths": [ "/login" ]
        }
    ]
  },
  "webcredentials": {
    "apps": ["1234.app.company.appname"]
  }
}

Upvotes: 6

luky
luky

Reputation: 2370

The reason in my case was an invalid JSON.

It didn't use " but ” because I copied it from some article and the "expert" author of the article put it with the signs like that, and I copied it from him.

BTW, there is still not the information box on the target site anyway like "you can open it with the app" but if i click the link eg from Notes app the app is opened.

wrong:

{
    “applinks”: {
        “apps”: [],
        “details”: [
            {
                “appID”: “T5TQ36Q2SQ.com.reddit.production”,
                “paths”: [“*”],
            }
        ]
    }
}

good:

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "T5TQ36Q2SQ.com.reddit.production",
                "paths": ["*"],
            }
        ]
    }
}

Upvotes: 2

Joshua Wolff
Joshua Wolff

Reputation: 3342

I did not see someone provide a solution for Flask.

This worked for me.

EDIT: After two down-votes, I'd like to clarify that I still use this exact solution months later. It does work, but there are other reasons why it might not work immediately for your app. This includes that you will have to delete the app and restart your phone several times even. Eventually, it links. I'm not sure why it is so difficult, but this solution does work. So keep trying, and if you have any issues, feel free to comment them so I can try to help.

If you are using Flask, put the "apple-app-site-association" in your static folder, and then add this to your application.py file.

@application.route('/apple-app-site-association', methods=['GET'])
def apple_app_site_association():
    return application.send_static_file('apple-app-site-association')

Upvotes: 1

Jorge Duque
Jorge Duque

Reputation: 61

For me, after implementing all the answers from above and testing that the AASA file was indeed being downloaded with mpoisot's answer, my issue was that in Xcode I added the associated domain as:

applinks:example.com

and in my notes app I was trying to use:

Https://example.com

because my AASA is not signed and I wanted to ensure I was serving it through HTTPS. So it worked when in my notes app I tried to use:

example.com

It works for me on a physical device, using iOS 12.1.2 with either a development build from Xcode or a distribution build from Testflight

Upvotes: 2

tanner burton
tanner burton

Reputation: 1159

After spending a day trying to get this to work, Restarting my phone solved the problem.

Uninstalling/Reinstalling the app didn't work either.

Upvotes: 5

mpoisot
mpoisot

Reputation: 8101

To help debugging this issue, search for "swcd" in your device's console output when installing your app to see if registering your universal link worked or failed.

  1. Use an actual device, not the simulator.
  2. Delete the app from you device.
  3. Connect the device to your computer, and view the device's console output in xcode. (window -> devices -> [your device] -> open console). Keep this window open.
  4. Install your app and let it launch.
  5. Filter the console output to "swcd". If it's sucessful you will see something like the folowing screenshot. If it fails you'll see something else. If you don't see anything then you messed something fundamental like adding the Associated Domains entitlement.

Applink added successfully

Upvotes: 86

nalexn
nalexn

Reputation: 10791

If you are hosting your apple-app-site-association on Firebase, make sure to put it in /.well-known/ subdirectory! It appears that Xcode queries that URL first, and if it succeeds, it makes no attempt to query the apple-app-site-association in the root directory. For some reason, firebase engineers made the hosted websites to automatically respond to /.well-known/apple-app-site-association with an empty (but correctly formed) association file that overrides your custom one, leaving you with no clue why nothing works!

Upvotes: 3

SparkyRobinson
SparkyRobinson

Reputation: 1522

Hope this helps someone because this took me about two days to figure out.

We had to add www. to our associated-domains in our .entitlements file.

        <string>applinks:www.yourdomain.com</string>
        <string>activitycontinuation:www.yourdomain.com</string>

Because if we used yourdomain.com instead of www.yourdomain.com our servers did a redirect -> 304 and then didn't include the content-type: application/json for the apple-app-site-association file.

N.B. the universal links still work for yourdomain.com and www.yourdomain.com

Upvotes: 3

IVtrue
IVtrue

Reputation: 1

I'll also put my notes on troubleshooting.

Basically we have 2 parts, that should be linked together: 1) web site and 2) an iOS app.

  1. For the web site there was only one issue: MIME type for apple-app-site-association file was not application/json.

    Also API Validation Tool wasn't helping us, for test environments it was saying

Error no apps with domain entitlements The entitlement data used to verify deep link dual authentication is from the current released version of your app. This data may take 48 hours to update.

but in the end web site was ok.

We checked web logs, saw GET request to apple-app-site-association file and decided to switch to iOS app.

  1. For dealing with iOS app setup it is good to have Console app running, with filtering for showing only swcd process, as was already mentioned in this thread.

In our case the issue was that we rely on wildcard URL, in the form: applinks:*.prod_site_name.com, thinking that * will cover all test environment prepending, like https://test_env.num4.prod_site_name.com, but this is not working. Console was showing:

Started request for domain '*.prod_site_name.com', URL 'https://prod_site_name.com/.well-known/apple-app-site-association'

So the fix in our case was to provide test-specific applinks for test target of the app, like: applinks:test_env.num4.prod_site_name.com

Upvotes: 0

Sebastian Boldt
Sebastian Boldt

Reputation: 5321

After two days of total desperation, I think I've finally fixed it. Here is my solution:

It seems that older apps use a different app prefix than newer apps. Newer apps only use the Team ID for this purpose. If the app prefix and the team ID are not identical, it seems that you need to specify the activity continuation field in the apple app site association file:

{
    "activitycontinuation": {
        "apps": [
            "YOUR_APP_PREFIX.de.company.app"
        ]
   },
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "YOUR_APP_PREFIX.de.company.app",
        "paths": ["/*"]
      }
    ]
  }
} 

Another thing I experienced during my hell ride was that deleting the app and restarting the device seems to be the only way to force refresh this file.

Upvotes: 2

Jeff Ward
Jeff Ward

Reputation: 18986

In my case, the request for the AASA file at: https://example.com/apple-app-site-association

Was being redirected to: https://www.example.com/apple-app-site-association

The kicker is -- this works fine on iOS 11, but fails on iOS 9.3.5. Go figure.

Solution: the apple-app-site-association file MUST NOT be behind a 302 or 301 redirect for iOS 9. (To be fair, this is noted on the UL troubleshooting page.)

Upvotes: 0

Vins
Vins

Reputation: 385

In my case my error was to put query parameters in paths:

{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "TEAM_ID.BundleIdentifier",
                "paths": [ "/auth-ui/hub?target=confirm&*" ]
            }
        ]
    }
}

when I remove '?target=confirm&*' from paths, it start to working

Upvotes: 1

morksinaanab
morksinaanab

Reputation: 732

For anyone who needs to easily test opening (Universal) Links, you can also open the link in your Simulator from the terminal with this command:

xcrun simctl openurl booted yourapp_or_http://yourlink

for example:

xcrun simctl openurl booted https://www.google.com

Upvotes: 21

Tiago Alves
Tiago Alves

Reputation: 1321

I was able to test Universal Links in the iOS Simulator by using the Calendar app.

I just created an event and added the URL I wanted to test in the event's URL field. Then, when viewing the created event, you can simply tap on the URL link and your app should open.

Upvotes: 1

Bence Pattogato
Bence Pattogato

Reputation: 3900

After two days it turned out for me, that these kind of links (from branch)

applinks:xxxx.app.link

work only after Archiving (also Ad-hoc) the application and install it to the phone.

Upvotes: 4

Related Questions