# AC-Powered Kiosk Display - Final Changes Summary ## Device Type: Android LED Displays (AC-Powered, Not Battery) ### Key Understanding These are **permanent display installations**, always plugged into power. The issue is **NOT** about battery drain, but about Android OS treating long-running apps as "idle" and killing them even when on AC power. --- ## What Was Fixed ### ✅ 1. Accurate Uptime Tracking **Problem:** Previous code calculated time since midnight, not actual app runtime **Solution:** Now tracks real app start time **Before:** ``` Health check performed - App uptime: 6 hours ← WRONG (should be 14h) ``` **After:** ``` Health check performed - App uptime: 14h 23m (started: 2026-02-26 20:00:00) ← CORRECT ``` --- ### ✅ 2. Kiosk Display Mode (Native Android) **Problem:** App treated as regular app, killed after 14 hours of "inactivity" **Solution:** Added window flags to prevent Android from sleeping/killing app ```kotlin window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD) window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) ``` **Result:** App stays in foreground, Android can't kill it for being "idle" --- ### ✅ 3. Connection Health Monitoring **Problem:** SignalR connection could die silently, no recovery **Solution:** - Health check every 5 minutes - Track consecutive failures - Auto-restart connection after 3 failures ```dart if (healthCheckFailures >= 3) { await queuingViewModel.stopHubConnection(); await Future.delayed(const Duration(seconds: 2)); await queuingViewModel.startHubConnection(); } ``` --- ### ✅ 4. Lifecycle Event Tracking **Problem:** No visibility when app goes to background or gets killed **Solution:** Log all lifecycle events with actual uptime **Now you'll see:** ``` [onAppPaused] - App uptime: 14h - WARNING: App going to background! [onAppDetached] - App uptime: 14h - CRITICAL: App being killed! ``` If app stays alive correctly, you should **NEVER** see these logs. --- ### ✅ 5. Clinic Prefix Validation **Added:** `isClinicPrefixAdded(String ticketNo)` method **Returns true only for:** `"XXX W-XX"` format (3 letters + space + W-) --- ## Files Changed 1. `lib/view_models/screen_config_view_model.dart` - Fixed uptime, health checks, lifecycle 2. `lib/models/global_config_model.dart` - Clinic prefix feature 3. `lib/repositories/signalR_repo.dart` - Connection improvements 4. `android/app/src/main/kotlin/.../MainActivity.kt` - Kiosk display mode 5. `android/app/src/main/AndroidManifest.xml` - Activity flags --- ## Why App Was Dying (Root Cause) Android has **App Standby Buckets** (Android 9+) and **Doze Mode** (Android 6+): - Even on AC power, Android monitors app activity - No user interaction = app considered "idle" - After ~12-24 hours, Android kills "idle" apps to free memory - **This happens even on plugged-in devices!** **Our Fix:** Window flags tell Android "this is a kiosk display, keep it alive" --- ## Deployment Steps ### 1. Build ```bash cd /Volumes/Data/Projects/Flutter/HMG_QLine flutter clean flutter build apk --release ``` ### 2. Deploy ```bash adb install -r build/app/outputs/flutter-apk/app-release.apk ``` ### 3. Verify **No user action needed** - app auto-configures for kiosk mode **Check logs for:** ``` MainActivity created - Kiosk display mode active Health check performed - App uptime: 0h 5m (started: 2026-03-01 10:54:37) ``` --- ## Expected Behavior After Fix | Time | Expected Log | |------|-------------| | **0-5 min** | `Health check performed - App uptime: 0h 5m` | | **1 hour** | `Health check performed - App uptime: 1h 0m` | | **14 hours** | `Health check performed - App uptime: 14h 0m` ← CRITICAL (previously died here) | | **24 hours** | `Health check performed - App uptime: 24h 0m` | | **48 hours** | `Health check performed - App uptime: 48h 0m` | | **60+ hours** | `WARNING: App running for 60+ hours - scheduling proactive restart` | --- ## What You Should NOT See If fix works correctly: - ❌ No `[onAppPaused]` logs (means going to background) - ❌ No `[onAppDetached]` logs (means being killed) - ❌ No gaps in health check logs (every 5 minutes without fail) --- ## If App Still Dies ### Scenario 1: Manufacturer-Specific Restrictions Some Android devices (Xiaomi, Oppo, Vivo, Realme) have **additional** task killers: **Solution:** 1. Go to device Settings > Apps > QLine 2. Enable "Auto-start" 3. Set Battery to "No restrictions" (even though it's AC powered) 4. Disable "Battery optimization" ### Scenario 2: Android Doze Override Needed ```bash # Whitelist app from doze restrictions adb shell dumpsys deviceidle whitelist +com.example.hmg_qline.hmg_qline # Verify adb shell dumpsys deviceidle whitelist | grep hmg_qline ``` ### Scenario 3: Full Kiosk Mode Required If above doesn't work, may need **Device Owner Mode**: ```bash adb shell dpm set-device-owner com.example.hmg_qline/.DeviceAdminReceiver ``` This gives app full control over device - cannot be killed by OS. --- ## Testing Checklist - [ ] Deploy new APK to test device - [ ] Check log: "MainActivity created - Kiosk display mode active" - [ ] Verify health checks appear every 5 minutes - [ ] Confirm uptime increments correctly (0h 5m → 0h 10m → 0h 15m) - [ ] Wait 14 hours - verify no `[onAppPaused]` or `[onAppDetached]` logs - [ ] Wait 24 hours - verify app still running - [ ] Disconnect network for 15 min - verify auto-reconnection - [ ] Check SignalR connection recovers automatically --- ## Success Metrics ✅ Health check logs every 5 minutes without gaps ✅ Uptime shows continuously (no resets except midnight restart) ✅ Hub connection stays alive ✅ App runs past 14-hour checkpoint ✅ App runs 48+ hours continuously ✅ No lifecycle events (paused/detached) in logs --- ## Emergency Commands ### Check if app is running: ```bash adb shell ps | grep hmg_qline ``` ### Check device idle state: ```bash adb shell dumpsys deviceidle ``` ### Force prevent app kill: ```bash adb shell cmd appops set com.example.hmg_qline.hmg_qline RUN_IN_BACKGROUND allow ``` ### View last 100 logs: ```bash adb logcat -t 100 | grep MainActivity ``` --- ## Contact for Issues If app still dies after these changes, provide: 1. Last 200 lines of logs before app stopped 2. Android version and device model 3. Screenshot of Apps > QLine > Battery settings 4. Output of: `adb shell dumpsys deviceidle whitelist`