Product Flavors позволяют собирать несколько вариантов Android-приложения из одной кодовой базы. У каждого flavor могут быть свои зависимости, ресурсы, исходники, manifest, application id, конфиги сервисов и Gradle-плагины. В проекте https://github.com/michaelbel/BuildFlavors через flavors собираются три версии приложения: gms для Google Play, hms для Huawei AppGallery и foss для F-Droid или устройств без проприетарных SDK.

Главная идея проекта: основной app-модуль работает с общим интерфейсом AppInteractor, а конкретная реализация подключается на этапе сборки в зависимости от выбранного flavor.

Что делает проект

В проекте есть три платформенные реализации:

Основной код приложения не знает, какая реализация сейчас внутри. MainViewModel получает только интерфейс:

@HiltViewModel
class MainViewModel @Inject constructor(
    private val appInteractor: AppInteractor
): ViewModel()

Когда пользователь нажимает кнопку, ViewModel вызывает один метод:

appInteractor.reportAnalyticsEvent(
    "ButtonClicked",
    Bundle().apply { putInt("count", count) }
)

А что произойдет дальше, зависит от flavor: Google отправит событие в Firebase, Huawei – в HiAnalytics, FOSS покажет, что событие не собирается.

Структура модулей

Проект разделен так:

app/
platform/
├── common/
├── gms/
├── hms/
├── foss/
└── inject/

platform:common содержит общий контракт.

platform:gms, platform:hms, platform:foss содержат разные реализации этого контракта.

platform:inject связывает контракт и реализацию через Hilt и подключает нужный платформенный модуль по flavor.