Skip to main content

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.

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.

Architectural layers

┌─────────────────────────────────────────────┐
│              UI (Jetpack Compose)            │
│        Screens, composables, dialogs         │
├─────────────────────────────────────────────┤
│                  ViewModels                  │
│     State holders, UI logic, user events     │
├─────────────────────────────────────────────┤
│                  Use cases                   │
│     Single-purpose business logic units      │
├─────────────────────────────────────────────┤
│                 Repositories                 │
│    Coordinate data sources, own the truth    │
├─────────────────────────────────────────────┤
│               Data sources                   │
│   Room database · API · Prefs · VPN service  │
└─────────────────────────────────────────────┘

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 single CoroutineScope (a MainScope) is provided by Hilt and injected wherever long-lived work is launched:
// di/AppModule.kt
@Provides
@Singleton
fun provideMainScope(): CoroutineScope = MainScope()
State is propagated as StateFlow or Flow. ViewModels collect these flows and expose them as StateFlow<UiState> to composables. The VPN state machine itself is built on MutableStateFlow:
// VpnStateMonitor.kt
private val statusInternal = MutableStateFlow(Status(Disabled, null))
override val status: StateFlow<Status> = statusInternal
Prefer stateIn(scope, SharingStarted.Eagerly, initial) when you need to convert a cold Flow into a hot StateFlow for the UI layer.

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/:
ModuleResponsibility
AppModule.ktCore singletons: API client, VPN backend provider, coroutine scope, dispatcher provider
AppDatabaseModule.ktRoom database construction and DAO provision
AuthModule.ktAuthentication-related bindings
CoreNetworkModule.ktOkHttp, certificate pins, DoH URLs
CoreAccountManagerModule.ktProton Core account manager
SdkModule.ktProTun VPN SDK binding
@Singleton is used for stateful services (VpnConnectionManager, VpnStateMonitor, CertificateRepository, ServerManager2). Use cases are typically @Reusable or unscoped.
// AppModule.kt — binding VpnConnectionManager as the VpnConnect interface
@Singleton
@Binds
fun bindVpnConnect(impl: VpnConnectionManager): VpnConnect

Room database

A single AppDatabase (version 54 as of this writing) consolidates all entities. It extends both VPN-specific database interfaces and Proton Core database interfaces:
// db/AppDatabase.kt
@Database(entities = [ /* 30+ entity classes */ ], version = AppDatabase.VERSION)
abstract class AppDatabase :
    BaseDatabase(),
    AccountDatabase,
    VpnRecentsDatabase,
    VpnProfilesDatabase,
    VpnUserDatabase,
    FeatureFlagDatabase,
    // … other Core databases
VPN-specific entities include:
  • RecentConnectionEntity / UnnamedRecentIntentEntity — recent connections
  • ProfileEntity — user-created connection profiles
  • ExcludedLocationEntity — split-tunneling excluded locations
  • VpnUser — cached VPN user data
  • PeriodicCallInfo — periodic update scheduling state
DAOs are provided through AppDatabaseDaoModule and injected into repositories.

Module organisation

app/src/main/java/com/protonvpn/android/
├── api/             # Retrofit API definitions and GuestHole
├── appconfig/       # AppConfig, feature flags, periodic updates
├── auth/            # Authentication use cases and data
├── db/              # AppDatabase, migrations
├── di/              # All Hilt modules
├── models/          # Domain models (VpnCountry, Server, ConnectionParams…)
├── profiles/        # Connection profiles
├── redesign/        # Rewritten UI: countries, recents, settings, VPN screens
├── servers/         # ServerManager2, ServersStore, streaming services
├── settings/        # User settings data layer
├── telemetry/       # VPN connection telemetry
├── ui/              # Legacy UI (home, onboarding, settings screens)
├── vpn/             # Core VPN logic: backends, state, certificates, error handling
│   ├── protun/      # ProTun backend (Proton VPN SDK)
│   └── wireguard/   # WireGuard backend (WireGuard Android library)
└── ProtonApplication.kt

Proton Core integration

The app links against several me.proton.core.* artifacts:
  • core-account — account entity, session management
  • core-auth — sign-in, SSO
  • core-network — OkHttp setup, DoH, API error handling
  • core-feature-flag — Unleash feature flags (fetched and cached in Room)
  • core-telemetry — event batching and upload
  • core-user / core-usersettings — user and settings entities
  • core-notification / core-push — notification infrastructure
  • core-observability — metric event funneling
Core database interfaces are bound to AppDatabase in AppDatabaseBindsModule, so Core repositories obtain their DAOs without knowing about the concrete database class.

Build docs developers (and LLMs) love