The ProtonVPN Android app follows a layered MVVM architecture enforced with Hilt dependency injection. Each layer has a single responsibility and communicates with adjacent layers through well-defined interfaces and reactive streams.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ProtonVPN/android-app/llms.txt
Use this file to discover all available pages before exploring further.
Architectural layers
UI layer
Built with Jetpack Compose. Screens observe
StateFlow and Flow from ViewModels. No business logic lives here.ViewModels
Android
ViewModel subclasses scoped to navigation destinations. Transform domain state into UI state and delegate user actions to use cases.Use cases
Focused, single-responsibility classes. Examples:
GetSmartProtocols, SettingsForConnection, ObserveExcludedLocations. Injected directly into ViewModels and managers.Repositories
Own the authoritative copy of a domain model (servers, certificates, recents). Merge API responses with locally persisted data.
Data sources
Room database (
AppDatabase), Retrofit API client (ProtonApiRetroFit), SharedPreferences, and the live VPN service state emitted by VpnBackend.Proton Core
The
me.proton.core.* libraries provide account management, authentication, networking, feature flags, telemetry, and more. The app binds Core interfaces in di/AppDatabaseModule.kt.Async model: coroutines and Flow
All asynchronous work uses Kotlin coroutines. A singleCoroutineScope (a MainScope) is provided by Hilt and injected wherever long-lived work is launched:
StateFlow or Flow. ViewModels collect these flows and expose them as StateFlow<UiState> to composables. The VPN state machine itself is built on MutableStateFlow:
Dependency injection with Hilt
The app uses Hilt (dagger.hilt.*) throughout. All Hilt modules are installed into SingletonComponent and live in app/src/main/java/com/protonvpn/android/di/:
| Module | Responsibility |
|---|---|
AppModule.kt | Core singletons: API client, VPN backend provider, coroutine scope, dispatcher provider |
AppDatabaseModule.kt | Room database construction and DAO provision |
AuthModule.kt | Authentication-related bindings |
CoreNetworkModule.kt | OkHttp, certificate pins, DoH URLs |
CoreAccountManagerModule.kt | Proton Core account manager |
SdkModule.kt | ProTun VPN SDK binding |
@Singleton is used for stateful services (VpnConnectionManager, VpnStateMonitor, CertificateRepository, ServerManager2). Use cases are typically @Reusable or unscoped.
Room database
A singleAppDatabase (version 54 as of this writing) consolidates all entities. It extends both VPN-specific database interfaces and Proton Core database interfaces:
RecentConnectionEntity/UnnamedRecentIntentEntity— recent connectionsProfileEntity— user-created connection profilesExcludedLocationEntity— split-tunneling excluded locationsVpnUser— cached VPN user dataPeriodicCallInfo— periodic update scheduling state
AppDatabaseDaoModule and injected into repositories.
Module organisation
Proton Core integration
The app links against severalme.proton.core.* artifacts:
core-account— account entity, session managementcore-auth— sign-in, SSOcore-network— OkHttp setup, DoH, API error handlingcore-feature-flag— Unleash feature flags (fetched and cached in Room)core-telemetry— event batching and uploadcore-user/core-usersettings— user and settings entitiescore-notification/core-push— notification infrastructurecore-observability— metric event funneling
AppDatabase in AppDatabaseBindsModule, so Core repositories obtain their DAOs without knowing about the concrete database class.