Requested Info
- SDK Version: expo": “^44.0.5”
- Platforms(Android/iOS/web/all): Android/iOS
- Add the appropriate “Tag” based on what Expo library you have a question on.
Problem
I am attempting to set up universal links for my expo app on Android and IOS. They are not working on either platform.
App Flow
- You start on an auth page that is a web view:
https://www.purchaseplan.io/app/auth/login
- If you choose the “Email” option, you type your email and receive a magic link in your inbox.
- That magic link redirects users back to
https://www.purchaseplan.io/app/auth/magic
- That page rediects users to
https://www.purchaseplan.io/app/auth/dashboard
Ideally, instead of opening in a browser, step 3 would open in my app.
Steps
1. AASA
To implement universal links on iOS, you must first set up verification that you own your domain. This is done by serving an Apple App Site Association (AASA) file from your webserver.
https://www.purchaseplan.io/.well-known/apple-app-site-association
returns the following:
{
"applinks": {
"apps": [],
"details": [
{
"appIDs": ["Q7RT2J2P3W.com.purchaseplan.ios"],
"components": [
{
"/": "*",
"comment": "home page"
},
{
"/": "/",
"comment": "home page"
},
{
"/": "/app/*",
"comment": "all /app pages"
},
{
"/": "/app/auth/*",
"comment": "all /auth pages"
},
{
"/": "/app/user/*",
"comment": "all /user pages"
}
]
},
{
"appID": "Q7RT2J2P3W.com.purchaseplan.ios",
"paths": ["*", "/*", "/app/*", "/app/auth/*", "/app/user/*"]
}
]
},
"activitycontinuation": {
"apps": [
"com.purchaseplan.ios",
"Q7RT2J2P3W.com.purchaseplan.ios"
]
}
}
2. AASA Validation
Branch provides an AASA validator which can help you confirm that your AASA is correctly deployed and has a valid format.
https://branch.io/resources/aasa-validator/
shows this is correct with the following response (all tests show passing)
www.purchaseplan.io
– This domain validates, JSON format is valid, and the Bundle and Apple App Prefixes match (if provided).
Below you’ll find a list of tests that were run and a copy of your apple-app-site-association file:
3. Expo Configuration
- Add the
associatedDomains
configuration to your app.json , and make sure to follow Apple’s specified format. Make sure not to include the protocol (https
) in your URL (this is a common mistake, and will result in your universal links not working).
Here’s my relevant app.json fields:
{
"expo": {
"scheme": "purchaseplan",
"name": "Purchase Plan",
"slug": "PurchasePlan",
"version": "69",
"ios": {
"bundleIdentifier": "com.purchaseplan.ios",
"associatedDomains": [
"applinks:purchaseplan.io",
"applinks:www.purchaseplan.io",
"activitycontinuation:purchaseplan.io",
"activitycontinuation:www.purchaseplan.io"
]
}
}
4. Apple Developer Configuration
- Edit your App ID on the Apple developer portal and enable the “Associated Domains” application service. Go into the App IDs section and click on your App ID. Select Edit, check the Associated Domains checkbox and click Done.
See this screenshot to see associated domains is checked:
5. Update Credentials
You will also need to regenerate your provisioning profile after adding the service to the App ID. This can be done by clearing your provisioning profile (which can be done via
expo credentials:manager
oreas credentials
, depending on if you useexpo build
oreas build
, respectively). Next time you build your app, Expo will prompt you to create a new provisioning profile.
I’ve done this. Not sure how to verify I did it correctly.
6. It should work?
At this point, opening a link on your mobile device should now open your app! If it doesn’t, re-check the previous steps to ensure that your AASA is valid, the path is specified in the AASA, and you have correctly configured your App ID in the Apple Developer Portal.
This step says it should work, but it doesn’t.
7. Android intent filters
You simply need to add
intentFilters
to the Android section of your app.json .
{
"expo": {
"android": {
"package": "com.purchaseplan.android",
"intentFilters": [
{
"action": "VIEW",
"autoVerify": true,
"data": [
{
"scheme": "https",
"host": "*.purchaseplan.io"
},
{
"scheme": "http",
"host": "*.purchaseplan.io"
},
{
"scheme": "https",
"host": "purchaseplan.io"
},
{
"scheme": "http",
"host": "purchaseplan.io"
}
],
"category": [
"BROWSABLE",
"DEFAULT"
]
}
]
}
}
8. Android asset links json
First, you must publish a JSON file at
/.well-known/assetlinks.json
specifying your app ID and which links should be opened by your app.
https://www.purchaseplan.io/.well-known/assetlinks.json
returns:
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.purchaseplan.android",
"sha256_cert_fingerprints": ["2F:79:E0:57:B9:1F:CE:F0:9B:BE:CB:22:47:65:01:01:9C:39:6B:DA:39:CF:C7:1E:48:FD:B8:42:64:0D:F3:63"]
}
}
Which is copied directly from google play for this purpose.
Note on intentFilters.data
I first tried it with a pathPrefix, then without it. Neither worked. The pathPrefix I tried was:
"pathPrefix": "/"
Conclusion
At this point, I expect it all to work. However, it doesn’t. Neither on iOS or Android. I suspect I’m misunderstanding or forgetting some basic step.