Files
Kordant/tasks/shieldai-unified-restructure/34-android-app-foundation.md
2026-05-25 12:23:23 -04:00

6.9 KiB

34. Android App — Jetpack Compose Foundation, Navigation, and Shared Theme

meta: id: shieldai-unified-restructure-34 feature: shieldai-unified-restructure priority: P1 depends_on: [shieldai-unified-restructure-01, shieldai-unified-restructure-02] tags: [android, jetpack-compose, foundation, navigation, mobile]

objective:

  • Establish the Android app foundation in android/: a Jetpack Compose project with app entry point, navigation architecture, and a shared theme system that mirrors the web app's ShieldAI brand palette with Material3 and dynamic dark mode support.

deliverables:

  • android/ directory with complete Android project:
    • app/build.gradle.kts — App module configuration
    • app/src/main/AndroidManifest.xml — App manifest with permissions
    • app/src/main/java/com/shieldai/android/MainActivity.kt — Entry point with setContent
    • app/src/main/java/com/shieldai/android/ShieldAIApp.kt — Application class
  • android/app/src/main/java/com/shieldai/android/ui/theme/ — Theme system:
    • Color.kt — All brand color tokens as Color constants:
      • BrandPrimary, BrandPrimaryLight, BrandPrimaryDark
      • BrandAccent, BrandAccentLight, BrandAccentDark
      • BgPrimary, BgSecondary, BgTertiary (light and dark variants)
      • TextPrimary, TextSecondary, TextTertiary
      • Success, Warning, Error, Info
    • Type.kt — Typography scale using Material3 Typography
    • Shape.kt — Corner radius shapes (small, medium, large)
    • Theme.ktShieldAITheme composable:
      • lightColorScheme() and darkColorScheme() using Material3
      • dynamicColor support for Android 12+ (optional)
      • Manual theme override state
  • android/app/src/main/java/com/shieldai/android/navigation/ — Navigation:
    • AppNavigation.kt — Navigation host with all routes
    • Screen.kt — Sealed class of all destinations with arguments
    • BottomNavBar.kt — Bottom navigation with 5 items: Dashboard, Services, Alerts, Settings, Account
    • NavGraph.kt — Compose Navigation graph definition
  • android/app/src/main/res/ — Resources:
    • mipmap-xxxhdpi/ — App icons for all densities
    • values/themes.xml — Base theme definitions
    • drawable/ — Vector icons and logos
  • Project configuration:
    • build.gradle.kts (project level) with Kotlin 2.0, Compose BOM
    • settings.gradle.kts including app module
    • Min SDK: 26 (Android 8.0), Target SDK: 35, Compile SDK: 35
    • Kotlin version: 2.0.0
    • Compose BOM: 2024.05.00 or latest stable

steps:

  1. Create android/ directory with standard Android project structure.
  2. Set up Gradle files:
    • Root build.gradle.kts: plugins block with com.android.application, org.jetbrains.kotlin.android
    • gradle/libs.versions.toml for version catalog (recommended)
    • App build.gradle.kts:
      android {
        compileSdk = 35
        defaultConfig {
          minSdk = 26
          targetSdk = 35
          applicationId = "com.shieldai.android"
        }
        buildFeatures { compose = true }
        composeOptions { kotlinCompilerExtensionVersion = "1.5.14" }
      }
      dependencies {
        implementation(platform("androidx.compose:compose-bom:2024.05.00"))
        implementation("androidx.compose.ui:ui")
        implementation("androidx.compose.material3:material3")
        implementation("androidx.navigation:navigation-compose:2.7.7")
        // ... other deps
      }
      
  3. Create theme system:
    • Color.kt: Define all colors as val BrandPrimary = Color(0xFF4F46E5) etc.
    • Type.kt: Create Typography with Inter font (download and add to res/font/)
    • Shape.kt: Shapes with small = RoundedCornerShape(8.dp), medium = 12.dp, large = 16.dp
    • Theme.kt:
      @Composable
      fun ShieldAITheme(
        darkTheme: Boolean = isSystemInDarkTheme(),
        dynamicColor: Boolean = false, // disable for brand consistency
        content: @Composable () -> Unit
      ) {
        val colorScheme = when {
          dynamicColor && Build.VERSION.SDK_INT >= 31 -> {
            if (darkTheme) dynamicDarkColorScheme(LocalContext.current)
            else dynamicLightColorScheme(LocalContext.current)
          }
          darkTheme -> DarkColorScheme
          else -> LightColorScheme
        }
        MaterialTheme(colorScheme = colorScheme, typography = Typography, shapes = Shapes, content = content)
      }
      
  4. Create navigation:
    • Screen sealed class: Dashboard, Services, Alerts, Settings, Account, Login, Signup, Onboarding, ServiceDetail(val service: String)
    • AppNavigation.kt: NavHost with rememberNavController()
    • BottomNavBar.kt: NavigationBar with 5 items, each with icon and label
    • Handle auth state: if unauthenticated, show Login as start destination
  5. Create MainActivity.kt:
    • setContent { ShieldAITheme { AppNavigation() } }
    • Handle window insets for edge-to-edge display
  6. Create ShieldAIApp.kt:
    • Application class for initialization (dependency injection setup, if used)
  7. Add app icons:
    • Convert ShieldAI logo SVG to vector drawable (res/drawable/ic_logo.xml)
    • Generate mipmap icons using Android Studio's Image Asset Studio
  8. Build and run on Android Emulator to verify app launches.

steps:

  • Unit: Theme switches correctly between light and dark modes
  • Unit: Navigation graph contains all expected destinations
  • Visual: App launches with correct bottom navigation and branding
  • Visual: Theme colors match web app palette in both modes

acceptance_criteria:

  • Android app builds and launches without crashes
  • Bottom navigation has 5 tabs with correct icons and labels
  • Theme colors match web app palette in both light and dark modes
  • Navigation between screens works with native Android transitions
  • App icon displays correctly on launcher
  • Theme supports manual override (light/dark/system)
  • Project uses modern Android stack: Kotlin 2.0, Compose, Material3

validation:

  • Build app in Android Studio and run on Pixel 7 emulator (API 34)
  • Toggle device dark mode and verify all colors shift
  • Navigate through all bottom tabs and verify transitions
  • Verify app icon on emulator home screen
  • Run ./gradlew test for unit tests

notes:

  • The Android app should feel native to Android, not like an iOS port. Use Material3 components, bottom sheets, floating action buttons, and Android-specific patterns.
  • Dynamic colors (Material You) are disabled by default to maintain brand consistency. Can be enabled as a user preference later.
  • Use Jetpack Compose Navigation with type-safe navigation arguments (Kotlin DSL or Navigation Compose 2.8+ typed navigation).
  • Consider using Hilt for dependency injection, but keep it simple for the initial setup.
  • The android/ directory is not part of the pnpm workspace. It is a standalone Gradle project.
  • For font loading, add Inter font files to res/font/ and reference them in Type.kt.