Product Flavor : définition, configuration et exemples dans Gradle

Auteur : IT Sectr Publié le : 2026-05-30 Temps de lecture : 9 min

Product Flavor dans le développement Android est un mécanisme Gradle qui permet de créer plusieurs variantes d'une même application à partir d'une base de code partagée. Chaque flavour peut avoir son propre applicationId, ses ressources, ses dépendances et ses fonctionnalités — par exemple, des versions gratuite et payante. Selon Google Android Developers, 2025, les Product Flavors font partie du système Build Variants et sont combinés avec les Build Types via flavorDimensions. Il s'agit de l'approche standard pour publier plusieurs versions d'une application sur Google Play.

Points clés

  • Product Flavor — une variante de produit avec un applicationId, des ressources et un code uniques.
  • Flavor Dimensions regroupent les flavors en axes indépendants pour une configuration multidimensionnelle.
  • Source sets pour un flavor remplacent les ressources principales : icônes, chaînes, manifeste.
  • Gradle génère automatiquement un Build Variant pour chaque combinaison de flavor + build type.
  • Google Play prend en charge la publication de plusieurs flavors en tant qu'applications séparées ou une seule avec différentes configurations.

Qu'est-ce que Product Flavor ?

Product Flavor est une configuration Gradle dans le bloc android.productFlavors qui décrit une variante de produit. Chaque flavor peut remplacer applicationId, versionName, versionCode, minSdkVersion, targetSdkVersion, signingConfig et d'autres paramètres de defaultConfig. Les Product Flavors n'ont pas de limite de quantité : un projet peut contenir 2, 5 ou 10 flavors — Gradle gère toutes les combinaisons.

Product Flavor résout le problème de réutilisation de la base de code (codebase reuse) — lorsque plusieurs applications différentes doivent être construites à partir d'un seul dépôt. Scénarios typiques : une version gratuite avec publicité et une version payante sans ; une version démo avec des fonctionnalités limitées ; des versions entreprise et grand public ; des applications white-label pour différents clients. Sans Product Flavors, chaque version devrait être maintenue dans un projet séparé, entraînant 60 à 70 % de duplication de code.

Historiquement, les Product Flavors sont apparus dans Android Gradle Plugin 0.9 (2013) en remplacement des configurations ant. Avant cela, les développeurs utilisaient des projets séparés pour différentes versions ou un remplacement manuel des ressources avant la construction. L'introduction des flavors dans AGP a unifié l'approche et en a fait le standard. Selon une enquête de JetBrains, 2024, 78 % des projets Android avec plusieurs versions utilisent Product Flavors, tandis que les autres utilisent la commutation manuelle via BuildConfig ou la réflexion.

Product Flavor vs Build Type

Build Type gère le processus de construction (debug avec débogage, release avec optimisation). Product Flavor gère le contenu de la construction (free sans fonctionnalités payantes, paid avec elles). Build Type est un paramètre d'infrastructure, Product Flavor est un paramètre de produit. Les deux concepts sont orthogonaux : une construction debug du flavor free diffère d'une construction release du flavor free uniquement par les paramètres de compilation, pas par les fonctionnalités. Product Flavor ne peut pas être utilisé pour désactiver le débogueur — c'est le rôle de Build Type.

Flavor Dimensions : organisation des dimensions

Ordre des dimensions et priorité

Flavor Dimensions sont un mécanisme de regroupement des Product Flavors en catégories indépendantes. Si une application a une version gratuite/payante et séparément une région américaine/européenne, les flavors sont regroupés en deux dimensions : « tier » (free, paid) et « region » (us, eu). Gradle crée le produit cartésien des dimensions : freeUs, freeEu, paidUs, paidEu — 4 variantes. Sans dimensions, Gradle traiterait les quatre flavors comme un seul plan, et un seul pourrait être sélectionné.

Les dimensions sont déclarées dans le bloc flavorDimensions sous forme de chaîne ou de liste de chaînes. L'ordre des dimensions affecte la priorité des source sets : la première dimension a la priorité la plus élevée. Si la dimension A (tier) est spécifiée en premier, alors src/free/ remplacera src/us/ en cas de conflit de ressources. L'ordre affecte également la façon dont le nom du Variant est formé : d'abord viennent les flavors de la première dimension, puis ceux de la deuxième, puis Build Type : freeUsDebug.

Le nombre de dimensions n'est pas limité, mais chaque nouvelle dimension multiplie le nombre de Build Variants. Pour un projet avec 4 dimensions (2 flavors chacune) et 2 build types, vous obtenez 2 × 2 × 2 × 2 × 2 = 32 variantes. La limite pratique est de 3 dimensions (maximum 8-12 variantes). Au-delà, la configuration Gradle ralentit et le panneau Build Variants dans Android Studio devient illisible.

groovy
android {
    flavorDimensions "tier", "api"

    productFlavors {
        free {
            dimension "tier"
            applicationId "com.example.app.free"
            versionNameSuffix "-free"
        }
        paid {
            dimension "tier"
            applicationId "com.example.app.paid"
        }
        minApi21 {
            dimension "api"
            minSdk 21
        }
        minApi26 {
            dimension "api"
            minSdk 26
        }
    }
}

// Résultat : freeMinApi21, freeMinApi26, paidMinApi21, paidMinApi26
// Chaque × debug/release = 8 Build Variants

Création de Product Flavors dans build.gradle

Kotlin DSL pour Product Flavors

Pour créer un Product Flavor, il faut ajouter un bloc productFlavors dans android, spécifier le nom du flavor et ses paramètres. La déclaration minimale d'un flavor est le nom et la dimension. Tous les autres paramètres sont hérités de defaultConfig et peuvent être remplacés. Le flavor hérite complètement de defaultConfig, y compris applicationId, versionCode, testInstrumentationRunner.

Chaque flavor peut remplacer applicationId — cela permet d'installer plusieurs versions de l'application sur le même appareil simultanément. Par exemple, la version gratuite sera com.example.app.free, la payante — com.example.app.paid. Si applicationId n'est pas remplacé, tous les flavors auront le même identifiant et ne pourront pas être installés côte à côte. applicationId doit correspondre au package dans le manifeste (sauf si applicationIdSuffix est utilisé).

AGP 8+ recommande d'utiliser Kotlin DSL au lieu de Groovy pour build.gradle. Kotlin DSL fournit un accès type-safe à la configuration : l'IDE suggère les noms des paramètres, vérifie les types à la compilation et met en évidence les erreurs. La migration de Groovy vers Kotlin DSL pour Product Flavors consiste généralement à remplacer les guillemets par des parenthèses et à ajouter des types. AGP est rétrocompatible — les deux syntaxes fonctionnent en parallèle dans le même projet.

kotlin
// build.gradle.kts — Kotlin DSL
android {
    flavorDimensions += "tier"

    productFlavors {
        register("free") {
            dimension = "tier"
            applicationId = "com.example.app.free"
            versionNameSuffix = "-free"
            buildConfigField("boolean", "IS_PREMIUM", "false")
        }
        register("paid") {
            dimension = "tier"
            applicationId = "com.example.app.paid"
            versionNameSuffix = "-paid"
            buildConfigField("boolean", "IS_PREMIUM", "true")
        }
    }
}

Ressources et code pour différents flavors

Chaque Product Flavor crée son propre source set — un répertoire src/<flavorName>/. Ce répertoire peut contenir des ressources remplacées, des fichiers sources et le manifeste. Le source set du flavor agit comme une superposition sur main : les fichiers de src/free/res/ remplacent les fichiers de src/main/res/ portant les mêmes noms. Cela permet d'avoir différentes chaînes, icônes, couleurs et mises en page pour chaque flavor sans modifier le code principal.

Pour remplacer des classes Java/Kotlin, il existe deux approches : l'implémentation spécifique au flavor (implémenter une classe abstraite dans chaque flavor) et le champ BuildConfig (branchement dans le code). La première approche est plus propre : vous définissez une interface ou une classe abstraite dans main, et des implémentations concrètes dans src/free/ et src/paid/. Lors de la construction, seule l'implémentation du flavor actuel est compilée. Cela offre des avantages simultanés : taille d'APK réduite (le code payant n'entre pas dans la version gratuite) et sécurité (il est impossible d'appeler accidentellement une fonction payante).

AndroidManifest.xml dans un source set de flavor ne remplace pas mais fusionne avec le manifeste principal. La fusion suit les règles Android : les attributs en double dans le même élément sont remplacés, les attributs uniques sont ajoutés. Par exemple, si le manifeste principal déclare l'autorisation INTERNET et que free ne le fait pas, l'autorisation Internet reste. Cependant, tools:node="replace" permet de remplacer un bloc entier du manifeste pour un flavor spécifique. Ceci est utile lorsque différents flavors nécessitent différentes autorisations (écriture sur SD pour paid, caméra pour free).

xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:label="Free App"
        tools:replace="android:label">
    </application>
</manifest>

Exemple : versions gratuite et payante de l'application

Considérons un scénario typique : free — une version avec publicité et fonctions de base, paid — sans publicité, avec des fonctionnalités étendues. Pour la version gratuite, applicationId est défini sur « com.example.app.free », pour la payante — « com.example.app.paid ». Les deux versions peuvent être installées sur le même appareil simultanément, car applicationId est l'identifiant unique de l'application dans le système Android.

Architecturalement, la séparation est construite via interface + implémentation de flavor. Dans le source set principal, l'interface PaymentService est déclarée. Dans src/free/, se trouve une implémentation qui affiche une publicité avant le paiement via AdMob. Dans src/paid/ — une implémentation qui procède directement à la passerelle de paiement. Le code utilisant PaymentService ne sait pas quelle implémentation est chargée — cela est résolu à la compilation. Cette approche garantit que le code de gestion des abonnements ne se retrouve pas dans la version gratuite, même si le développeur l'appelle accidentellement.

La taille de l'APK pour différents flavors peut différer de 5 à 15 Mo en raison de l'inclusion/exclusion de dépendances. Pour exclure une bibliothèque d'un flavor spécifique, utilisez des dépendances spécifiques au flavor dans build.gradle : freeImplementation 'com.google.android.gms:play-services-ads:23.0.0'. Cette dépendance sera ajoutée uniquement pour la variante gratuite et n'augmentera pas la taille de la version payante. Pour les dépendances partagées, utilisez implementation — tous les flavors les incluent.

kotlin
// src/main/kotlin/com/example/payment/PaymentService.kt
interface PaymentService {
    fun processOrder(amount: Double, callback: (PaymentResult) -> Unit)
}

// src/free/kotlin/.../FreePaymentService.kt
class FreePaymentService : PaymentService {
    override fun processOrder(amount: Double, callback: (PaymentResult) -> Unit) {
        AdManager.showInterstitial {
            PaymentGateway.charge(amount, callback)
        }
    }
}

// src/paid/kotlin/.../PaidPaymentService.kt
class PaidPaymentService : PaymentService {
    override fun processOrder(amount: Double, callback: (PaymentResult) -> Unit) {
        PaymentGateway.charge(amount, callback)
    }
}

Product Flavor dans les projets multimodules

Dans les projets multimodules, les modules de bibliothèque peuvent ne pas avoir leurs propres Product Flavors, ce qui crée un problème : la bibliothèque est construite une fois (en release), tandis que le module app avec flavor attend la bibliothèque avec la variante correspondante. À partir d'AGP 8.1, les bibliothèques peuvent publier plusieurs variantes via le bloc publishing.multipleVariants — cela permet de publier toutes les variantes de flavor de la bibliothèque dans un seul dépôt maven, et le module app sélectionnera automatiquement la bonne.

Une approche alternative consiste à déclarer les mêmes flavorDimensions et productFlavors dans la bibliothèque que dans le module app. AGP fait correspondre automatiquement les flavors par correspondance exacte de nom dans une dimension. Si le nom du flavor dans la bibliothèque correspond au nom dans l'app, AGP créera des variantes cohérentes. Pour faciliter la maintenance, il est recommandé d'extraire les définitions communes de flavor dans un Convention Plugin — un plugin Gradle appliqué à tous les modules du projet.

Pour les bibliothèques non destinées à la publication (modules internes), il suffit de synchroniser les flavors via le build.gradle du projet racine. Gradle fournit la méthode subprojects, qui permet d'appliquer une configuration à tous les sous-projets. Cependant, gardez à l'esprit qu'une trop grande configuration dans subprojects ralentit la phase de configuration. Il est recommandé d'utiliser des Convention Plugins — ils sont compilés une fois et réutilisés, réduisant le temps de configuration de 15 à 30 %.

Foire aux questions

Combien de Product Flavors peut-on créer ?

Il n'y a pas de limite de quantité, mais chaque dimension multiplie le nombre de Build Variants. 4 flavors dans une dimension + 2 build types = 8 variantes. 4 + 4 dans deux dimensions = 16 variantes. Il est recommandé de ne pas utiliser plus de 3 dimensions et 10 à 12 variantes au total.

Peut-on remplacer le manifeste pour un flavor ?

Oui, via le source set src/<flavor>/AndroidManifest.xml. Le manifeste fusionne avec le principal. Pour remplacer un bloc entier, utilisez tools:node="replace". Par exemple, remplacez le libellé de l'application ou les autorisations pour un flavor spécifique.

Comment ajouter des dépendances spécifiques à un flavor ?

Utilisez la configuration <flavorName>Implementation. Exemple : freeImplementation 'com.google.android.gms:play-services-ads:23.0.0'. Cette dépendance sera incluse uniquement lors de la construction de la variante gratuite. Pour la payante : paidImplementation. Les dépendances communes sont spécifiées via implementation.

Quelle est la différence entre Product Flavor et Build Type ?

Product Flavor définit la version du produit (free, paid, demo), Build Type définit la méthode de construction (debug, release). Les flavors peuvent remplacer applicationId, versionName, les ressources. Build Type contrôle debuggable, minification, signing. Les deux sont orthogonaux et se combinent en Build Variant.

Peut-on utiliser Product Flavor avec Jetpack Compose ?

Oui, les Product Flavors fonctionnent avec Compose sans restriction. Différents flavors peuvent avoir différents écrans Compose via des source sets ou des implémentations de classes abstraites. Vous pouvez également ajouter des dépendances Compose spécifiques à un flavor : freeImplementation 'androidx.compose.ui:ui-tooling'.

Résumé

  • Product Flavor — un mécanisme Gradle pour créer plusieurs versions d'une application à partir d'une seule base de code.
  • Flavor Dimensions regroupent les flavors en dimensions, permettant de combiner différents aspects de l'application.
  • Source sets pour un flavor remplacent les ressources, le code et le manifeste sans modifier le répertoire principal.
  • Interface + implémentation de flavor est une approche architecturale propre pour séparer les fonctionnalités.
  • Dépendances spécifiques à un flavor empêchent les bibliothèques inutiles de se retrouver dans des versions inappropriées.
  • Projets multimodules nécessitent une synchronisation des flavors via des Convention Plugins ou la publication de plusieurs variantes.
  • Recommandation : pas plus de 3 dimensions de flavor et pas plus de 10 Build Variants au total dans un projet.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi