Chapitre 2
02 - Android Natif
02 - Android Natif
02 - Android Natif : Cours complet
Table des matières
- Android Studio et structure de projet
- Gradle, Kotlin DSL, version catalog, AGP
- Le Manifest Android
- Activities & Fragments
- ViewModel & LiveData
- Le système de resources
- Build variants
- minSdk, targetSdk, compileSdk
- Jetifier et migrations
- Résumé et checklist
1. Android Studio et structure de projet
1.1 Android Studio
Android Studio est l'IDE officiel (basé sur IntelliJ IDEA), maintenu par Google, distribué gratuitement.
Fonctionnalités clés :
- Éditeur Kotlin/XML avec refactoring ;
- Layout Inspector : inspecter la hiérarchie UI d'un écran en cours d'exécution ;
- Android Profiler : CPU, mémoire, réseau, énergie ;
- Emulator : AVD (Android Virtual Device) ;
- Debugger, inspecteur de base de données, Git intégré ;
- Tools > Device Manager pour gérer les appareils.
1.2 Structure d'un projet moderne
MyApp/
├── settings.gradle.kts # repositories + include modules
├── build.gradle.kts # configuration racine (plugins)
├── gradle/
│ ├── libs.versions.toml # version catalog
│ └── wrapper/gradle-wrapper.properties
├── gradle.properties # options JVM, AndroidX flags
├── local.properties # sdk.dir (non versionné)
├── gradlew / gradlew.bat
└── app/
├── build.gradle.kts # config du module app
├── proguard-rules.pro
└── src/
├── main/
│ ├── java/com/example/myapp/
│ │ ├── MainActivity.kt
│ │ └── ui/...
│ ├── res/
│ │ ├── layout/ drawable/ values/ mipmap/ xml/
│ └── AndroidManifest.xml
├── debug/ # ressources/sources debug uniquement
└── release/
1.3 Le dossier res
| Dossier | Contenu |
|---|---|
layout/ | Layouts XML (ou composables en Kotlin) |
drawable/ | Images vectorielles/bitmap, formes |
values/ | strings.xml, colors.xml, themes.xml, dimens.xml |
mipmap/ | Icônes de lanceur (plusieurs densités) |
xml/ | Configurations (backup rules, network security) |
font/ | Polices en resources |
2. Gradle, Kotlin DSL, version catalog, AGP
2.1 Rôle de Gradle
Gradle est le système de build : il compile, packagé (AAB), gère les dépendances et les tâches personnalisées. Depuis Android Gradle Plugin (AGP) 9 (2025), le Kotlin DSL est le standard (le Groovy est déprécié).
2.2 Version catalog (gradle/libs.versions.toml)
Centralise les versions pour éviter les incohérences.
[versions]
agp = "8.9.0"
kotlin = "2.2.0"
compose-bom = "2025.12.01"
coreKtx = "1.16.0"
lifecycle = "2.9.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
compose-ui = { group = "androidx.compose.ui", name = "ui" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
2.3 build.gradle.kts du module
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}
android {
namespace = "com.example.myapp"
compileSdk = 36
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 24
targetSdk = 36
versionCode = 1
versionName = "1.0.0"
}
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
buildFeatures {
compose = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
dependencies {
implementation(platform(libs.compose.bom))
implementation(libs.androidx.core.ktx)
implementation(libs.compose.ui)
}
2.4 AGP (Android Gradle Plugin)
- Version majeure ↔ Gradle requis (table de compatibilité dans la doc).
- AGP 8.x : JDK 17+ requis, namespaces obligatoires.
- AGP 9 (2025+) : Kotlin DSL par défaut, les plugins Kotlin et AGP versionnés séparément.
agpVersions: un plugin plus récent que le Gradle installé échoue au démarrage.
2.5 Bonnes pratiques Gradle
- Utiliser le wrapper (
gradlew) et committergradle-wrapper.properties. - Éviter les versions en dur : tout passe par le version catalog.
- Activer la configuration cache pour accélérer les builds.
gradle.properties:org.gradle.jvmargs=-Xmx4g,org.gradle.caching=true.
3. Le Manifest Android
3.1 Structure
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/Theme.MyApp"
android:supportsRtl="true">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
3.2 Composants déclarables
| Composant | Rôle | Déclaration |
|---|---|---|
| Activity | Écran | <activity> |
| Service | Tâche de fond | <service> |
| BroadcastReceiver | Réaction aux événements système | <receiver> |
| ContentProvider | Partage de données | <provider> |
3.3 Permissions
- Install-time : accordées à l'installation (ex. INTERNET).
- Runtime : demandées à l'exécution (caméra, localisation, micro…).
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf(Manifest.permission.CAMERA), REQ_CAMERA)
}
Depuis Android 11+, la location en arrière-plan exige une permission séparée (ACCESS_BACKGROUND_LOCATION) et une justification dans le store.
3.4 Intent filters
L'intent-filter déclare ce que le composant peut recevoir.
<activity android:name=".ShareActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
4. Activities & Fragments
4.1 La back stack
Diagramme en cours de génération...
startActivity(intent)empile une nouvelle Activity.- Le bouton back dépile.
FLAG_ACTIVITY_CLEAR_TOP,SingleTop,singleTaskmodifient ce comportement.
4.2 Les Fragments
Un Fragment = morceau d'UI + de logique attaché à une Activity.
class ListFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
inflater.inflate(R.layout.fragment_list, container, false)
}
Ajout dynamique :
supportFragmentManager.beginTransaction()
.replace(R.id.container, ListFragment())
.addToBackStack(null)
.commit()
Limitations connues des Fragments (documentées par Google en 2024) : lifecycle complexe, fuites faciles, bugs de transactions. Recommandation Google : les éviter quand un écran simple suffit ; les garder pour la navigation multi-panneaux. Avec Jetpack Compose, on utilise plutôt la Navigation Compose (chapitre 04).
4.3 ViewLifecycleOwner
Dans un Fragment, les vues vivent entre onCreateView et onDestroyView : les collectes de LiveData/Flow doivent observer le ViewLifecycleOwner, pas le Fragment.
4.4 Recomendations
- 1 Activity pour app simple ; navigation par Navigation Component (04).
- Lifecycle-aware components via
lifecycleScopeetrepeatOnLifecycle.
5. ViewModel & LiveData
5.1 ViewModel
Le ViewModel survit à la rotation et conserve les données en mémoire.
class ProfileViewModel(private val repo: ProfileRepository) : ViewModel() {
private val _profile = MutableLiveData<Profile?>()
val profile: LiveData<Profile?> = _profile
init {
viewModelScope.launch {
_profile.value = repo.fetchProfile()
}
}
}
viewModelScope: annulé quand le ViewModel est cleared.- Factory pour injecter des dépendances (voir Hilt, chapitres 03/04).
5.2 LiveData
LiveData = observable respectueux du lifecycle : il ne délivre que si l'observateur est STARTED ou plus.
viewModel.profile.observe(viewLifecycleOwner) { profile ->
// mise à jour UI, exécutée seulement si actif
}
Avantages : aucune fuite (auto-unsubscribe), aucune mise à jour d'un écran en arrière-plan.
Limitations : valeurs uniques (pas de séquences), postValue écrase les valeurs rapides. Recommandation moderne : préférer StateFlow/Flow (chapitre 03), LiveData reste utile pour les anciennes bases et le binding XML.
5.3 Séparation des préoccupations
Diagramme en cours de génération...
6. Le système de resources
6.1 Principe
Les ressources sont séparées du code et qualifiées par configuration (locale, densité, orientation, mode nuit…).
6.2 Qualifiers courants
| Qualifier | Exemple | Usage |
|---|---|---|
| Langue | values-fr/ | Traductions |
| Densité | drawable-xxhdpi/ | Images |
| Taille | values-sw600dp/ | Tablettes |
| Orientation | layout-land/ | Paysage |
| Nuit | values-night/ | Thème sombre |
| API | values-v33/ | Comportements API 33+ |
6.3 Localisation
<!-- res/values/strings.xml -->
<string name="greeting">Hello</string>
<!-- res/values-fr/strings.xml -->
<string name="greeting">Bonjour</string>
textView.text = getString(R.string.greeting)
Ne jamais écrire de texte en dur dans les layouts (lint l'interdit).
6.4 Alternatives : Compose
Avec Compose, les resources restent utilisées : stringResource(R.string.greeting), LocalConfiguration.current.locales pour la locale.
7. Build variants
7.1 Le modèle debug/release
| Debug | Release | |
|---|---|---|
| Débogable | Oui | Non |
| Minify | Non | Oui (R8) |
| Signature | Debug keystore | Release keystore |
| Adresse API | dev | prod |
| Perf | Ralentie | Optimisée |
7.2 Flavors (produits)
flavorDimensions += "environment"
productFlavors {
create("free") { dimension = "environment" }
create("paid") { dimension = "environment" }
}
Résultat : freeDebug, freeRelease, paidDebug, paidRelease. Chaque variant a son propre src/free/ etc.
7.3 BuildConfig & sources par variant
buildTypes {
debug {
buildConfigField("String", "API_URL", "\"https://dev.example.com\"")
}
release {
buildConfigField("String", "API_URL", "\"https://api.example.com\"")
}
}
Le choix du variant se fait dans Android Studio (Build Variants tool window) ou via ./gradlew assembleRelease.
8. minSdk, targetSdk, compileSdk
| Paramètre | Rôle | Exemple |
|---|---|---|
compileSdk | Version de l'API utilisée pour compiler | 36 |
minSdk | Version minimale prise en charge | 24 |
targetSdk | Version déclarée comme cible : définit les comportements activés | 36 |
targetSdkVersion (historique) | Alias de targetSdk | — |
8.1 Règles d'or
- targetSdk : obligatoirement à jour pour publier (Play Store exige la version récente). Déclenche les changements de comportement (ex. scoped storage, foreground service types, edge-to-edge).
- minSdk : choix produit ; chaque API 16 points de parts de marché perdus ≈ 0 (voir distribution des versions sur Google). En 2026, minSdk 24 est un minimum raisonnable.
- compileSdk : toujours la dernière stable (ex. 36 pour Android 16) pour les nouvelles APIs, sauf si une lib l'exige.
- Ne jamais mettre compileSdk < targetSdk.
8.2 Impact des comportements targetSdk
| API | Comportement activé selon targetSdk |
|---|---|
| 30 | Scoped storage obligatoire |
| 31 | Foreground service types obligatoires |
| 33 | Permission notifications runtime |
| 34 | Edge-to-edge par défaut |
| 35 | Partial screen sharing, intent filters |
9. Jetifier et migrations
9.1 Que sont les support libraries ?
Avant androidx, Google livrait les « Android Support Libraries » (android.support.*). En 2018, elles ont été renommées AndroidX (androidx.*). Depuis, les anciennes libs ne reçoivent plus de mises à jour.
9.2 Jetifier
Jetifier est un outil de Gradle (AGP) qui réécrit automatiquement les binaires des dépendances encore écrites avec android.support.* vers androidx.*.
# gradle.properties
android.enableJetifier=true # coûteux en build : à retirer dès que possible
android.useAndroidX=true
Règles :
useAndroidX=trueest obligatoire pour toute lib AndroidX.enableJetifier=truene doit être activé que si une dépendance tierce utilise encoreandroid.support.*; il dégrade la performance de build.- Objectif : supprimer Jetifier et migrer les libs.
9.3 Migration support → AndroidX
- Activer
useAndroidX=true. - Lancer « Migrate to AndroidX » dans Android Studio.
- Retirer
enableJetifierquand plus aucunsupport.*n'est détecté. - Vérifier :
./gradlew dependencieset un build release.
10. Résumé et checklist
10.1 Points clés
- Android Studio : Layout Inspector, Profiler, AVD sont des alliés.
- Gradle : version catalog + Kotlin DSL = configuration saine et rapide.
- Manifest : déclare composants, permissions, intent filters.
- Activities empilent ; Fragments modularisent (avec leurs pièges).
- ViewModel + LiveData : état résilient et observateur lifecycle-aware.
- Resources qualifiées : multilangue, densités, thème nuit sans code.
- Build variants : debug/release + flavors = environnements séparés.
- SDKs : compileSdk le plus récent, targetSdk à jour, minSdk = compromis produit.
- Jetifier : pont temporaire, à éliminer.
10.2 Checklist
- Je structure un projet Android Studio avec version catalog
- J'explique le rôle de chaque élément du Manifest
- Je sais déclarer et demander une permission runtime
- Je connais le lifecycle d'une Activity et d'un Fragment
- Je crée un ViewModel et j'observe une LiveData au bon owner
- Je localise mon app (strings + qualifiers)
- Je configure debug/release et des flavors
- Je choisis minSdk/targetSdk/compileSdk avec argument
- Je sais quand et pourquoi retirer Jetifier
Prochain chapitre
→ 03-Kotlin : langage Kotlin, coroutines, Ktor, sérialisation, DI, K2, multiplatform.