Bedrud Documentation

L’application Android Bedrud est construite avec Jetpack Compose et Kotlin, offrant une expérience native de réunion vidéo avec picture-in-picture, deep linking et multi-instance support.

Technology Stack

TechnologyVersionPurpose
Kotlin2.1.0Language
Jetpack ComposeMaterial 3UI toolkit
Koin4.0.0Dependency injection
Retrofit + OkHttpLatestHTTP client
LiveKit Android SDK2.23.3WebRTC media
Credentials APILatestPasskey support
Encrypted SharedPreferencesLatestSecure storage
CoilLatestImage loading

Target : Min SDK 28, Target SDK 35, JDK 17

Directory Structure

apps/android/app/src/main/java/com/bedrud/app/
├── BedrudApplication.kt           # Application class (Koin init)
├── MainActivity.kt                # Single-activity entry point
├── core/
│   ├── api/                       # Retrofit API client
│   │   ├── ApiClient.kt           # Base HTTP client avec auth interceptor
│   │   ├── AuthApi.kt             # Auth endpoint definitions
│   │   └── RoomApi.kt             # Room endpoint definitions
│   ├── auth/
│   │   └── AuthManager.kt         # Token management, login/logout
│   ├── call/
│   │   ├── CallService.kt         # Foreground service pour les appels
│   │   └── CallConnectionService.kt  # Android ConnectionService
│   ├── deeplink/
│   │   └── DeepLinkHandler.kt     # Handle bedrud.com deep links
│   ├── di/
│   │   └── AppModule.kt           # Koin module definitions
│   ├── instance/
│   │   ├── InstanceManager.kt     # Central multi-instance orchestrator
│   │   ├── InstanceStore.kt       # Persistent instance storage
│   │   └── InstanceDeps.kt        # Per-instance dependency container
│   ├── livekit/
│   │   └── RoomManager.kt         # LiveKit room connection manager
│   └── pip/
│       └── PipManager.kt          # Picture-in-Picture controller
├── models/
│   ├── User.kt                    # User data model
│   ├── Room.kt                    # Room data model
│   ├── Instance.kt                # Server instance model
│   └── ApiResponse.kt             # API response wrappers
└── ui/
    ├── screens/
    │   ├── auth/
    │   │   ├── LoginScreen.kt     # Email/password + passkey login
    │   │   └── RegisterScreen.kt  # Account registration
    │   ├── dashboard/
    │   │   └── DashboardScreen.kt # Room list et management
    │   ├── meeting/
    │   │   └── MeetingScreen.kt   # Video call interface
    │   ├── instance/
    │   │   ├── AddInstanceScreen.kt    # Add server instance
    │   │   └── InstanceSwitcher.kt     # Switch between instances
    │   ├── profile/
    │   │   └── ProfileScreen.kt   # User profile
    │   └── settings/
    │       └── SettingsScreen.kt  # App settings
    ├── components/                 # Reusable Compose components
    └── theme/                      # Material 3 theme definition

Multi-Instance Architecture

L’application Android prend en charge la connexion simultanée à plusieurs Bedrud servers.

flowchart TB
    subgraph IM ["InstanceManager (Koin singleton)"]
        IS["InstanceStore<br/>Persists list to SharedPreferences"]
        AI["Active Instance (StateFlow)"]
        INST["instances: List Instance"]
    end
 
    subgraph DEPS ["InstanceDeps"]
        AM["AuthManager"]
        AC["ApiClient"]
        AA["AuthApi"]
        RA["RoomApi"]
        PM["PasskeyManager"]
        RM["RoomManager"]
    end
 
    AI --> DEPS

Key Pattern

Toutes les per-instance dependencies sont exposées comme StateFlow<T?> sur InstanceManager. Les composables les collectent :

val authManager = instanceManager.authManager.collectAsState().value ?: return
val roomApi = instanceManager.roomApi.collectAsState().value ?: return

Le motif ?: return garantit que le composable ne render pas tant que l’instance n’est pas fully initialized.

flowchart LR
    A["No instances"] --> B[AddInstanceScreen]
    C["Has instances, not logged in"] --> D[LoginScreen]
    E["Has instances, logged in"] --> F[DashboardScreen]

L’instance switcher apparaît comme un ModalBottomSheet déclenché depuis le Dashboard toolbar.

Features

Deep Linking

L’app gère les URLs correspondant à :

  • https://bedrud.com/m/* - Direct room join
  • https://bedrud.com/c/* - Room join by code

Configuré via les intent filters dans AndroidManifest.xml.

Call Management

  • CallService - Foreground service qui maintient la connexion active pendant les appels
  • CallConnectionService - S’intègre au Android’s telephony framework pour une proper call UI
  • Permissions requises : MANAGE_OWN_CALLS, FOREGROUND_SERVICE_PHONE_CALL, FOREGROUND_SERVICE_CAMERA, FOREGROUND_SERVICE_MICROPHONE

Picture-in-Picture

L’écran de réunion prend en charge le PiP mode, permettant aux utilisateurs de voir la video feed tout en utilisant d’autres apps.

Passkeys

Utilise l’Android’s Credentials API pour le FIDO2/WebAuthn passkey registration et login.

Building

# Debug APK
make build-android-debug
 
# Release APK (requiert keystore.properties)
make build-android
 
# Build + install sur le connected device
make release-android
 
# Ouvrir dans Android Studio
make dev-android

Release Signing

Les release builds nécessitent un keystore.properties file dans le android project root avec votre signing configuration.