Skip to Content

Chapitre 5.5 — Deep links : ouvrir l’app au bon endroit

Où on en est : Drill navigue parfaitement… quand on est dedans. Dernier maillon : y entrer directement au bon écran depuis l’extérieur — la notification du défi quotidien (Partie 9) en dépend.

⏱️ TL;DR — Le scheme: "drill" d’app.json fait de drill://… une porte d’entrée : chaque route est automatiquement un deep link avec Expo Router. Test : npx uri-scheme open "drill://quiz?theme=php" --android. Les écrans doivent être robustes à l’entrée directe (params validés, données manquantes gérées). Les App Links https (vérifiés par domaine) : panorama — utile le jour où Drill aura un site.

🎯 Objectifs

  • Comprendre le chemin scheme → route → écran (rien à câbler : Expo Router mappe seul).
  • Tester des deep links sur le téléphone/émulateur.
  • Rendre les écrans robustes à l’ouverture directe (le contrat du chapitre 5.3 payé cash).
  • Situer custom scheme vs App Links https.

Comment ça marche

Rappel chapitre 2.5 : "scheme": "drill" dans app.json. Au build, Android enregistre l’app comme handler des URLs drill://. Expo Router fait le reste : l’URL est mappée sur vos routes de fichiers, sans configuration :

drill:// → app ouverte (accueil) drill://themes → onglet Thèmes drill://themes/symfony → détail du thème Symfony drill://quiz?theme=php&count=10 → une session PHP démarre !

Deux cas de figure gérés automatiquement : app fermée (démarrage directement sur l’écran cible) et app en arrière-plan (ramenée au premier plan, navigation vers la cible).

Tester

# Sur l'émulateur ou le téléphone connecté (adb requis — chapitre 2.3) npx uri-scheme open "drill://themes/symfony" --android # Équivalent adb brut : adb shell am start -a android.intent.action.VIEW -d "drill://quiz?theme=php&count=5"

⚠️ Piège — Dans Expo Go, votre scheme drill:// n’existe pas (l’app conteneur a le sien : exp://). Les deep links custom se testent en préfixant : npx uri-scheme open "exp://192.168.1.x:8081/--/quiz?theme=php" --android (le /--/ sépare l’adresse Metro du chemin). Le vrai drill:// sera testable sur le development build (Partie 11) et l’APK (Partie 12). Notez la manip Expo Go quelque part — elle déroute tout le monde.

La robustesse d’entrée directe

Un écran atteint par deep link n’a aucun contexte : personne n’a « préparé » les données sur l’écran précédent. Trois contrats à respecter — et bonne nouvelle, on les a déjà posés :

  1. Params validés avec défauts (chapitre 5.3) : drill://quiz?count=999 → borné à 50 ; ?theme=inexistant → thème mélange ou écran d’erreur propre.
  2. Données chargeables depuis n’importe où : le détail d’un thème charge par slug (pas de « données passées par l’écran précédent » — anti-pattern de navigation).
  3. Pile de retour cohérente : back depuis un écran deep-linké doit mener quelque part de sensé (l’accueil), pas fermer brutalement l’app. Expo Router reconstruit la pile d’après l’arborescence (un deep link vers /themes/symfony place /themes dessous) — testez-le.

Le cas d’usage réel arrive en Partie 9 : la notification « 🔥 Ton défi quotidien t’attend » portera drill://quiz?theme=<aléatoire>&count=5 — tap → directement en jeu. C’est LE pont notifications ↔ navigation.

Les schemes custom ont deux limites : n’importe quelle app peut déclarer drill:// (pas de propriété), et un lien drill:// dans un navigateur ne fait rien si l’app manque. Les Android App Links résolvent ça : des URLs https normales (https://drill.app/quiz) vérifiées par un fichier assetlinks.json hébergé sur le domaine — l’app s’ouvre si installée, le site sinon.

Configuration : intentFilters dans app.json + le fichier sur le domaine. Hors périmètre pratique pour Drill (pas de site, pas d’hébergement — ADR 0001), mais sachez que ça existe : le jour où une de vos apps a un site, c’est le standard. 🍏 Côté iOS : l’équivalent s’appelle Universal Links (fichier apple-app-site-association).

✏️ Exercices

1. Testez trois deep links vers Drill dans Expo Go (accueil, détail Symfony, quiz avec params). Notez la commande exacte qui fonctionne chez vous.

✅ Solution

npx uri-scheme open "exp://<IP>:8081/--/" --android npx uri-scheme open "exp://<IP>:8081/--/themes/symfony" --android npx uri-scheme open "exp://<IP>:8081/--/quiz?theme=php&count=5" --android

(IP = celle affichée par Metro.) Vérifier : l’écran cible s’affiche, et le back mène à un endroit sensé. Le drill:// natif attendra le dev build.

2. Forgez un deep link hostile : …/--/quiz?theme=<script>&count=-3. Que doit-il se passer, et où est le code qui le garantit ?

✅ Solution

Aucun crash : theme inconnu → fallback (mélange ou erreur propre), count=-3 → borné à 5 minimum. Le code : la lecture défensive des params dans app/quiz.tsx (chapitre 5.3). Un deep link est une entrée utilisateur non fiable — au même titre qu’un formulaire.

3. Depuis l’écran résultat, ajoutez « Partager ce défi » : construire l’URL drill://quiz?theme=X&count=N de la session et la copier au presse-papiers (anticipation Partie 9 : expo-clipboard).

✅ Solution

import * as Clipboard from 'expo-clipboard' const url = `drill://quiz?theme=${summary.theme}&count=${summary.count}` <Button label="Copier le défi" variant="ghost" onPress={() => Clipboard.setStringAsync(url)} />

(npx expo install expo-clipboard.) Un ami avec Drill installé qui ouvre cette URL tombe sur LA même config de session. Le partage complet (Share sheet) arrive en Partie 9.

🧠 Quiz

Réponse

Uniquement le scheme dans app.json (“drill”) — Expo Router mappe automatiquement les URLs drill://chemin sur l’arborescence de app/.

Réponse

Via le scheme d’Expo Go : exp://<ip-metro>:8081/--/<chemin> (le /--/ sépare) avec npx uri-scheme open … --android. Le scheme natif exige un dev build/APK.

3. Citez les trois contrats de robustesse d’un écran deep-linkable.

Réponse

Params validés avec défauts sûrs ; données chargeables par identifiant (aucune dépendance à l’écran précédent) ; pile de retour cohérente (back sensé).

Réponse

App Links = URLs https réelles, vérifiées par le domaine (assetlinks.json) : propriété garantie + fallback web si l’app manque. Custom scheme = simple et sans domaine, mais non exclusif et sans fallback.

Réponse

La notification du défi quotidien : tap → drill://quiz?theme=…&count=5 → directement en partie.


👉 Partie suivante : Partie 6 — État & formulaires — Zustand, la machine d’état d’une partie, et les réglages persistés : Drill devient jouable.