Cos'è il deep linking
Il deep linking permette di aprire una schermata specifica della tua app a partire da un link esterno: un'email, un messaggio, un sito web o una notifica. Invece di portare l'utente sulla home, lo si conduce direttamente al contenuto desiderato, ad esempio una pagina prodotto (https://miosito.it/prodotti/42).
Esistono diverse tipologie di link che Flutter può intercettare:
- Custom URL scheme: link del tipo
miapp://prodotti/42. Semplici da configurare ma poco sicuri e con UX limitata. - Universal Links (iOS) e App Links (Android): usano URL
httpsreali e verificati. Sono lo standard consigliato perché aprono l'app se installata, altrimenti il browser.
In questa guida vediamo come gestire entrambi con il pacchetto app_links integrato con go_router.
Installazione
Aggiungi le dipendenze al pubspec.yaml:
dependencies:
app_links: ^6.3.0
go_router: ^14.0.0
Configurazione Android (App Links)
Nel file android/app/src/main/AndroidManifest.xml, all'interno dell'<activity> principale, aggiungi un intent filter:
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="miosito.it" />
</intent-filter>
L'attributo android:autoVerify="true" richiede di pubblicare un file assetlinks.json su https://miosito.it/.well-known/assetlinks.json:
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "it.miosito.miapp",
"sha256_cert_fingerprints": ["FA:C6:17:..."]
}
}]
Il fingerprint SHA-256 si ottiene dalla chiave di firma con keytool o dalla Google Play Console.
Configurazione iOS (Universal Links)
In Xcode, sotto Signing & Capabilities, aggiungi la capability Associated Domains e inserisci:
applinks:miosito.it
Sul server pubblica https://miosito.it/.well-known/apple-app-site-association (senza estensione, con Content-Type: application/json):
{
"applinks": {
"apps": [],
"details": [{
"appID": "TEAMID.it.miosito.miapp",
"paths": ["/prodotti/*"]
}]
}
}
Intercettare i link nel codice
Il pacchetto app_links gestisce due scenari: l'app aperta da chiusa (cold start) e l'app già in esecuzione in background.
import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart';
class DeepLinkHandler {
final AppLinks _appLinks = AppLinks();
final GoRouter router;
DeepLinkHandler(this.router);
Future<void> init() async {
// Link che ha avviato l'app da chiusa
final initialUri = await _appLinks.getInitialLink();
if (initialUri != null) {
_handleUri(initialUri);
}
// Link ricevuti mentre l'app è attiva
_appLinks.uriLinkStream.listen((uri) {
_handleUri(uri);
});
}
void _handleUri(Uri uri) {
// Es: https://miosito.it/prodotti/42 -> /prodotti/42
router.go(uri.path);
}
}
Integrazione con go_router
Definisci le rotte che corrispondono ai path dei tuoi link:
final router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => const HomeScreen(),
),
GoRoute(
path: '/prodotti/:id',
builder: (context, state) {
final id = state.pathParameters['id']!;
return ProdottoScreen(id: id);
},
),
],
);
Inizializza l'handler dopo aver creato il router:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final handler = DeepLinkHandler(router);
await handler.init();
runApp(MyApp(router: router));
}
Nota: go_router include un supporto nativo al deep linking tramite il sistema di routing della piattaforma. Tuttavia, usare
app_linksesplicitamente dà maggiore controllo, soprattutto quando serve gestire la logica prima della navigazione (es. autenticazione o tracciamento).
Testare i deep link
Durante lo sviluppo puoi simulare un link senza configurare il server.
Su Android:
adb shell am start -a android.intent.action.VIEW \
-d "https://miosito.it/prodotti/42" it.miosito.miapp
Su iOS (simulatore):
xcrun simctl openurl booted "https://miosito.it/prodotti/42"
Best practice
- Valida sempre i parametri ricevuti dai link: un utente potrebbe manipolare l'URL.
- Gestisci i fallback: se il contenuto non esiste, mostra una schermata di errore invece di crashare.
- Proteggi le rotte sensibili con controlli di autenticazione tramite il
redirectdi go_router. - Verifica i file di associazione: usa lo strumento Statement List Tester di Google per Android e i tool Apple per iOS.
Conclusione
Il deep linking trasforma l'esperienza utente, collegando il mondo web alla tua app in modo fluido. Combinando app_links per intercettare gli URL e go_router per la navigazione dichiarativa, ottieni una soluzione robusta e mantenibile. La parte più delicata resta la corretta configurazione dei file di verifica lato server: una volta superato quello scoglio, i tuoi Universal Links e App Links funzioneranno in modo trasparente su entrambe le piattaforme.
