Skip to Content

Chapitre 12.1 — L’identité de l’app

Où on en est : Drill builde, mais porte encore l’icône par défaut et un splash blanc. Avant le premier build de production : l’identité visuelle complète — celle qu’on ne change plus (ou peu) ensuite.

⏱️ TL;DR — Quatre pièces : le nom (court : « Drill »), le package name (com.alex.drill — IMMUABLE après la première installation sérieuse), l’icône adaptative Android (foreground + fond, cadrée pour les masques ronds/squircle), et le splash screen (expo-splash-screen : logo centré sur fond sombre, hideAsync piloté pour couvrir l’hydratation). Tout se déclare dans app.config.ts — zéro natif.

🎯 Objectifs

  • Fixer les identifiants (nom, package) en comprenant ce qui est irréversible.
  • Fabriquer une icône adaptative correcte (les dimensions et la safe zone qui piègent).
  • Configurer le splash et le faire durer JUSTE assez (hydratation, ch. 6.4).
  • Poser la checklist d’identité réutilisable pour chaque nouvelle app.

Le nom et le package — l’irréversible d’abord

// app.config.ts — rappel des champs d'identité (ch. 11.3) name: IS_DEV ? 'Drill Dev' : 'Drill', android: { package: IS_DEV ? 'com.alex.drill.dev' : 'com.alex.drill' },
  • Le nom : court (l’espace sous l’icône est ~11 caractères avant troncature), sans sous-titre — « Drill », pas « Drill — quiz pour devs ».
  • Le package name : la vraie identité système (notation domaine inversé — com.<vous>.<app> ; le domaine n’a pas besoin d’exister). IMMUABLE : le changer = une AUTRE app pour Android (et pour le Play Store à jamais, P13). Les données SQLite, réglages, la continuité des mises à jour — tout y est attaché. On le choisit une fois, bien, maintenant.

L’icône adaptative Android

Android ne prend pas une image carrée simple : l’adaptive icon = un foreground (votre logo, PNG 1024×1024, fond transparent) + un background (couleur ou image), que CHAQUE launcher masque à sa façon (rond, squircle, goutte…) et anime (parallaxe) :

android: { adaptiveIcon: { foregroundImage: './assets/images/adaptive-icon.png', // 1024×1024, transparent backgroundColor: '#0b1216', // notre ink-950 }, }, icon: './assets/images/icon.png', // fallback carré 1024 (vieux launchers, divers)

LE piège dimensionnel : le masque ne garde que le cercle central (~66 %) du foreground — votre logo doit tenir dans une safe zone de ~700 px au centre du canevas 1024. Un logo pleine largeur = oreilles coupées sur tous les téléphones. Pour Drill : un « D » éclair (ou 🎯 stylisé) cyan #58c4dc, occupant ~55 % du canevas, sur fond ink.

Où fabriquer ça sans être designer : Figma (canevas 1024 + cercle-guide 66 %), l’excellent Icon Kitchen  (prévisualise tous les masques), export PNG. Vérité de terrain : une icône SIMPLE (une lettre, un glyphe, deux couleurs) bat un dessin détaillé — elle se lit à 48 px.

Le splash screen

L’écran affiché par le SYSTÈME entre le tap et votre premier rendu — pas optionnel : sans config, c’est un flash blanc (hideux en app sombre) :

// app.config.ts plugins: [ ['expo-splash-screen', { image: './assets/images/splash-icon.png', // logo seul, ~400 px, centré par le plugin backgroundColor: '#0b1216', imageWidth: 180, }], ],

Et le contrôle du MOMENT où il disparaît — le raccord avec l’hydratation du ch. 6.4 :

// app/_layout.tsx import * as SplashScreen from 'expo-splash-screen' SplashScreen.preventAutoHideAsync() // top-level : le splash reste export default function RootLayout() { const settingsHydrated = useSettings.persist.hasHydrated() useEffect(() => { if (settingsHydrated) SplashScreen.hideAsync() // on lève le rideau quand on est prêt }, [settingsHydrated]) // … }

Le pattern : le splash couvre le chargement des fondations (réglages hydratés, thème connu) — l’utilisateur passe du logo à un écran FINI, jamais à un flash de thème ou un squelette. Et la règle de durée : le splash dure ce que dure le travail — l’allonger « pour le branding » est une insulte à l’utilisateur.

⚠️ Piège — L’icône et le splash sont cuits dans le binaire AU BUILD : les changer = rebuild + réinstallation (jamais d’OTA pour ça — ch. 12.5). D’où ce chapitre AVANT les builds de prod : on fige l’identité d’abord, on builde ensuite. Vérifiez sur PLUSIEURS launchers (émulateur Pixel + votre téléphone) : les masques diffèrent vraiment.

💡 Pour un dev Next.js — C’est le favicon/manifest/theme-color du web, avec un cran d’irréversibilité en plus (le package name n’a aucun équivalent web — pensez-y comme un nom de domaine qu’on ne pourrait JAMAIS migrer). Le splash ≈ le loading.tsx racine : même rôle, même règle (couvrir le vrai travail, pas décorer).

La checklist d’identité (à recopier pour chaque app)

  • Nom court (≤ 11 caractères affichés)
  • Package name définitif com.<moi>.<app> (+ .dev en variante)
  • Foreground 1024×1024 transparent, logo dans la safe zone 66 %
  • backgroundColor de l’icône = couleur de marque sombre
  • icon.png 1024 carré (fallback)
  • Splash : logo ~180 px sur fond de marque, preventAutoHideAsync + hide à l’hydratation
  • notification-icon monochrome blanc (déjà fait ch. 9.2 — même famille)
  • Vérifié sur 2 launchers + mode clair/sombre du tiroir d’apps

✏️ Exercices

1. Fabriquez la vraie icône de Drill (Icon Kitchen ou Figma), branchez-la, rebuild du dev build, et vérifiez la safe zone sur l’émulateur Pixel (masque cercle) ET votre téléphone.

✅ Solution

Icon Kitchen : glyphe/lettre, foreground cyan #58c4dc, fond #0b1216, export → remplacer les PNG → npx expo run:android. Vérif : l’icône ne doit rien perdre d’important au masque rond ; si le logo touche les bords → réduire à ~55 % du canevas. Bonus : le long-press sur l’icône (menu contextuel) révèle encore un autre cadrage — la safe zone pardonne tout.

2. Chronométrez le splash : ajoutez un console.log(Date.now()) au preventAutoHide et au hideAsync. Combien dure-t-il à froid ? À chaud ? Que couvre-t-il exactement dans Drill ?

✅ Solution

Attendu : 300-800 ms à froid (Hermes + hydratation AsyncStorage + premier rendu), < 200 ms à chaud. Il couvre : le chargement du bundle, l’hydratation des settings (notre condition), le premier layout. Si > 1,5 s à froid : chercher ce qui bloque le premier rendu (import lourd top-level, requête synchrone) — le splash est aussi un instrument de mesure.

3. Pourquoi le package name de la variante dev (com.alex.drill.dev) doit-il être décidé EN MÊME TEMPS que celui de prod, et que se passerait-il si vous changiez com.alex.drill en com.alexl.drill dans 6 mois ?

✅ Solution

Les deux forment l’espace d’identité de l’app (les données de chacune y sont liées). Changer dans 6 mois : Android verrait une app NEUVE — installation côte à côte avec l’ancienne, historique SQLite/réglages NON transférés, et sur le Play Store ce serait une nouvelle fiche (avis, stats perdus — P13). Migration possible mais douloureuse (export/import manuel). D’où : 5 minutes de réflexion maintenant, zéro regret ensuite.

🧠 Quiz

1. Quel champ d’identité est immuable, et pourquoi ?

Réponse

Le package name : c’est l’identité système (données, mises à jour, continuité store). Le changer crée une autre app aux yeux d’Android — et du Play Store.

2. De quoi se compose une icône adaptative, et quelle est la contrainte clé ?

Réponse

Foreground (logo 1024 transparent) + background (couleur/image), masqués par chaque launcher. Contrainte : le logo dans la safe zone centrale ~66 % — hors d’elle, c’est coupé.

3. Comment synchronise-t-on la disparition du splash avec l’app ?

Réponse

SplashScreen.preventAutoHideAsync() au chargement, puis hideAsync() quand les fondations sont prêtes (settings hydratés) — le rideau se lève sur un écran fini.

4. Peut-on changer l’icône par OTA ?

Réponse

Non : icône et splash sont cuits dans le binaire au build — les changer exige rebuild + réinstallation. L’OTA (ch. 12.5) ne touche que le JS.

5. Citez trois éléments de la checklist d’identité.

Réponse

Nom court, package définitif (+ variante .dev), foreground en safe zone, fond de marque, splash piloté par l’hydratation, icône de notification monochrome, vérification multi-launchers.


👉 Chapitre suivant : 12.2 — EAS Build en production — le premier binaire de prod, dans le cloud.