6

Background:

  • our app uses different bundle ids for development builds vs beta builds vs production (App Store) builds
  • I am currently implementing Universal Links in our development builds
  • Our production build currently in the App Store does not support Universal Links

I am experiencing this crazy issue where not only are my Universal Links not opening the development version of the app, they are launching the production version instead, despite the production version not having the proper entitlements.

My apple-app-site-association file has been validated using both https://branch.io/resources/universal-links/ and https://search.developer.apple.com/appsearch-validation-tool/ and looks like so:

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "DY74R9XXXX.com.myapp.consumer.debug",
        "paths": [ "/profiles/*", "/messages/*"]
      },
      {
        "appID": "DY74R9XXXX.com.myapp.consumer",
        "paths": [ "/profiles/*", "/messages/*"]
      }
    ]
  }
}

According to https://developer.apple.com/library/ios/documentation/General/Conceptual/AppSearch/UniversalLinks.html the details array should be evaluated in order and stop after finding a match.

The order of the dictionaries in the array determines the order the system follows when looking for a match, so you can specify an app to handle a particular part of your website.

The intention is that the same Universal Link will load in the development version for anyone on my team, and in the production version for end-users who don't have the .debug package on their phone.

Not only does this not work, but as mentioned, the Universal Links always load the production version, even though the production version lacks the applinks:dev.myserver.com entitlement that points to me apple-app-site-association file. This seems crazy but it would imply that I can launch arbitrary packages that I didn't publish and that the entitlements file isn't enforced.

Furthermore, if I remove the second entry from the details array and only leave the dictionary for the debug version, the Universal Links fail to work, and open Safari instead. Switching the order of the array has no effect either. I have experienced this behavior on an iPhone 6s on both 9.3 and 9.3.1. Any advice on these two isses (launching the wrong package, and not launching the debug package when it's the only entry) is greatly appreciated!

emkman
  • 812
  • 12
  • 21
  • Bizarre as this seems, it sounds like iOS is somehow conflating the entitlements between `DY74R9XXXX.com.myapp.consumer.debug` and `DY74R9XXXX.com.myapp.consumer`, perhaps because they are so similar. This is definitely not documented anywhere. Could you try changing the bundle ID for the debug build to something that is unambiguously different? – Alex Bauer Apr 19 '16 at 04:19
  • @AlexBauer you seem right about the entitlements getting confused due to similarity, but this wouldn't explain why it doesn't work with only one details entry. However, based on your suggestion I changed the bundle ID to `com.myapp.dev` and it worked. I then changed it to `com.myapp.dev.dev` and this worked as wel (I was concerned about a bug with 4 level identifiers vs the typical 3). Any suggestions on next steps? – emkman Apr 19 '16 at 05:19
  • 1
    The `apple-app-site-association` file is only pulled when the app is installed. Assuming this is actually a caching issue, I think you'd have to delete *both* app builds each time to get a clean test. If you were only deleting and reinstalling one of them, I could see how that would cause these lingering issues. – Alex Bauer Apr 19 '16 at 16:21
  • @AlexBauer I found the exact cause and it wasn't caching. See my updated answer below. Thanks for all your help! – emkman Apr 19 '16 at 20:37
  • That's awesome. Thank you for the update! – Alex Bauer Apr 20 '16 at 00:19

2 Answers2

2

This wasn't a caching issue - updated resolution below

Original Answer:

After changing my bundle ID to something different at the third level, per Alex Bauer's suggestion, I was able to get the links to work. I then changed my bundle ID back to com.myapp.consumer.debug and they continued to work. So this may have been a weird caching related bug with the swcd service. However, if I move the DY74R9XXXX.com.myapp.consumer entry to the first spot in the array, it will continue to launch the consumer version even though it lacks entitlements. This seems like a potentially separate or additional bug related to four level bundle IDs and incorrect matching.

Updated/Correct Solution

Changing the bundle ID and then changing it back actually fixed the issue because it modified my Info.plist and project.pbxproj files. When I viewed the diff the true issue became apparent. We were previously setting our bundle ID via this value in the Info.plist:

<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)${BUNDLE_ID_SUFFIX}</string>

with a static PRODUCT_BUNDLE_IDENTIFIER in our project.pbxproj. This was based on previously published common practices for multiple env builds. However, in XCode 7 Apple has strongly recommend upgrading settings so that Info.plist always contains:

<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>

This was never an issue before as far as building and submitting to iTunes with the proper package name. However, it is now clear that certain features require this exact setting, as noted here: Use Bundle Identifier instead of Product Bundle Identifier with Xcode 7

I set the Product Bundle ID for each build type via XCode as seen here and now everything works as expected.

TL;DR - Universal Links target your PRODUCT_BUNDLE_IDENTIFIER, not your CFBundleIdentifier. If your PRODUCT_BUNDLE_IDENTIFIER does not match the final bundle ID of your package, Universal Links will not work correctly.

Community
  • 1
  • 1
emkman
  • 812
  • 12
  • 21
  • Thanks for highlight issue. I try to fix by change in PRODUCT_BUNDLE_IDENTIFIER but it's giving error: _An invalid value 'XC $CB_APP_ID' was provided for the parameter 'appIdName'. Provisioning profile "iOS Team Provisioning Profile: *" doesn't support the Associated Domains capability. Provisioning profile "iOS Team Provisioning Profile: *" doesn't include the com.apple.developer.associated-domains entitlement. Code signing is required for product type 'Application' in SDK 'iOS 10.0'_ Could you please check ? – CoDe Jan 10 '17 at 08:24
1

Other solution in case if you are working with multiple target & multiple Firebase project.

  1. Create entitlements file each for target and
  2. Create different Deep link in Firbase Console.
  3. Use App_code from Firebase Console to update entitlements file -> Associated_Domain name.

That's it. Generate link form using different app_code. It will launch respected application.

CoDe
  • 11,056
  • 14
  • 90
  • 197