{
"expo": {
"scheme": "myapp",
"ios": {
"associatedDomains": [
"applinks:myapp.com"
]
},
"android": {
"intentFilters": [
{
"action": "VIEW",
"autoVerify": true,
"data": [
{
"scheme": "https",
"host": "myapp.com",
"pathPrefix": "/"
}
],
"category": [
"BROWSABLE",
"DEFAULT"
]
}
]
}
}
}Am implementat recent deep linking universal într-o aplicație de e-commerce cu vreo 25k de utilizatori activi, folosind Expo Router v3. Sună simplu pe hârtie: pui niște rute în directorul app, configurezi un domeniu și totul ar trebui să meargă. În realitate, m-am lovit de toate ciudățeniile posibile, de la cache-ul agresiv al Apple pe fișierele de asociere până la semnăturile SHA-256 din Google Play Console.
Dacă vrei să scapi de migrene și să configurezi corect atât custom schemes, cât și Universal Links (iOS) și App Links (Android), am adunat aici pașii concreți care mi-au salvat proiectul.
Schema Custom vs. Link-uri Universale: Trade-off-ul necesar
Multe echipe se opresc la custom scheme (de genul myapp://produs/123). E simplu de configurat și merge brici în faza de dezvoltare. Problema apare în producție: dacă userul dă click pe un astfel de link dintr-un browser sau din mail și nu are aplicația instalată, va primi o eroare urâtă de sistem.
Universal Links (iOS) și App Links (Android) folosesc URL-uri standard de HTTPS (de exemplu, https://myapp.com/produs/123). Dacă aplicația e instalată, se deschide instant, fără confirmări dubioase. Dacă nu e instalată, userul ajunge frumos pe site-ul tău web, unde poți să-i arăți un buton de "Descarcă din App Store".
Trade-off-ul? Configurarea pe server e destul de rigidă și necesită acces la domeniul de producție (HTTPS obligatoriu).
Configurarea corectă în app.json
Expo Router simplifică mult lucrurile pentru că mapează automat structura de directoare la URL-uri. Totuși, trebuie să-i spunem sistemului de operare ce domenii controlăm.
Pe iOS, ai nevoie de cheia associatedDomains sub nodul ios. Atenție mare: domeniul trebuie prefixat obligatoriu cu applinks:.
Pe Android, lucrurile se fac prin intentFilters. Trebuie să declari explicit că aplicația ta știe să deschidă schemele de tip http și https pentru domeniul tău.
Fișierele de pe server (AASA și AssetLinks)
Aici se rupe filmul pentru majoritatea developerilor. Ca sistemele de operare să aibă încredere în aplicația ta, trebuie să pui câte un fișier JSON pe serverul web asociat domeniului tău.
Pentru iOS, pui fișierul la adresa https://domeniu.ro/.well-known/apple-app-site-association. Atenție: fișierul NU trebuie să aibă extensia .json în URL și trebuie servit cu content-type: application/json. Apple cache-uiește agresiv acest fișier pe serverele lor CDN. Dacă ai greșit un ID de echipă, modificarea poate dura și 24 de ore până se propagă la utilizatori.
Pentru Android, pui fișierul la https://domeniu.ro/.well-known/assetlinks.json. Aici e mai simplu, dar ai grijă să folosești amprenta SHA-256 din Google Play Console (cea de "App signing key"), nu cheia de upload sau cheia locală de debug. Altfel, pe varianta de producție descărcată din magazin link-urile nu se vor deschide direct.
Cum testăm asta local?
Nu încerca să testezi Universal Links direct pe simulator introducând link-ul în Safari; adesea nu funcționează așa. Folosește terminalul.
Pentru iOS, pornește simulatorul și rulează:
xcrun simctl openurl booted https://domeniu.ro/produs/123
Dacă folosești un server local pentru teste (de exemplu, prin ngrok), asigură-te că rulezi tunelul pe HTTPS și că ai adăugat URL-ul de ngrok în app.json înainte de a face build-ul de development.
Voi cum gestionați fallback-ul în web pentru userii care nu au aplicația instalată? Mergeți pe o pagină simplă cu "Descarcă din Store" sau aveți o clonă web completă a aplicației?