dt# Quick Summary - Changes Made (March 1, 2026) ## Device Context **Important:** These are **AC-powered Android LED kiosk displays**, not battery-powered tablets. The issue is not battery drain, but Android OS killing "idle" apps even on plugged-in devices. ## Problem Identified from Logs - App started ~midnight Feb 26 - Ran successfully with health checks until 8:36 AM Feb 27 (~14 hours) - **Completely stopped logging** after 8:36 AM - No crash logs, no lifecycle events - User manually restarted March 1 at 10:54 AM ## Root Cause **Android OS killed the app** after ~14 hours because: 1. Android treats long-running apps as "idle" even on AC power 2. No user interaction for extended periods 3. Android's background task restrictions kicked in 4. App wasn't in proper kiosk/foreground mode --- ## Critical Changes Made ### 1. **Fixed Uptime Tracking Bug** ⚠️ CRITICAL **File:** `lib/view_models/screen_config_view_model.dart` **Problem:** ```dart // WRONG - calculated time since last MIDNIGHT, not app start DateTime.now().difference(lastChecked).inHours ``` **Solution:** ```dart DateTime appStartTime = DateTime.now(); // Track actual start time final uptimeHours = DateTime.now().difference(appStartTime).inHours; ``` **Impact:** Now you'll see accurate uptime like: ``` Health check performed - App uptime: 14h 23m (started: 2026-02-26 20:00:00) ``` --- ### 2. **Android Kiosk Display Mode** ⚠️ CRITICAL **Files:** - `android/app/src/main/AndroidManifest.xml` - `android/app/src/main/kotlin/.../MainActivity.kt` **Changes:** 1. Added window flags to prevent sleep/idle: ```kotlin override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) 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) } ``` 2. Added activity flags in manifest: ```xml android:keepScreenOn="true" android:screenOrientation="portrait" ``` **Impact:** Prevents Android from treating app as "idle" and killing it. No user dialogs needed - works automatically. --- ### 3. **Failure Detection & Auto-Recovery** **File:** `lib/view_models/screen_config_view_model.dart` **Added:** - Track consecutive health check failures - After 3 failures, automatically restart SignalR connection - Log critical warnings ```dart int healthCheckFailures = 0; try { syncHubConnectionState(); healthCheckFailures = 0; // Reset on success } catch (e) { healthCheckFailures++; if (healthCheckFailures >= 3) { // Restart connection await queuingViewModel.stopHubConnection(); await Future.delayed(const Duration(seconds: 2)); await queuingViewModel.startHubConnection(); } } ``` --- ### 4. **Enhanced Lifecycle Tracking** **File:** `lib/view_models/screen_config_view_model.dart` **Changes:** - Log actual uptime in lifecycle events - Track when app goes to background - Track when app is killed **New Logs:** ``` [onAppPaused] - App uptime: 14h - WARNING: App going to background! [onAppDetached] - App uptime: 14h - CRITICAL: App being killed! ``` **Impact:** You'll now see EXACTLY when and why the app dies --- ### 5. **Clinic Prefix Feature** **File:** `lib/models/global_config_model.dart` **Added:** ```dart bool globalClinicPrefixReq = false; bool clinicPrefixReq = true; bool isClinicPrefixAdded(String ticketNo) { final hasClinicPrefix = RegExp(r'^[A-Za-z]{3} W-').hasMatch(ticketNo); return hasClinicPrefix; } ``` **Returns true for:** `"XXX W-78"` (3 letters + space + W-) **Returns false for:** `"W-A-12"`, `"XX-12"`, `"X-7"`, etc. --- ## Files Modified 1. ✅ `lib/view_models/screen_config_view_model.dart` 2. ✅ `lib/models/global_config_model.dart` 3. ✅ `lib/repositories/signalR_repo.dart` 4. ✅ `android/app/src/main/AndroidManifest.xml` 5. ✅ `android/app/src/main/kotlin/.../MainActivity.kt` 6. ✅ `CHANGES_EXPLANATION.md` (full documentation) --- ## Next Steps - Deploy & Test ### 1. Build APK ```bash cd /Volumes/Data/Projects/Flutter/HMG_QLine flutter clean flutter build apk --release ``` ### 2. Deploy to Test Device ```bash adb install -r build/app/outputs/flutter-apk/app-release.apk ``` ### 3. First Launch Actions - **No user action required!** - App automatically configures kiosk display mode - Check logs to verify health checks are running ### 4. Monitor Logs Look for these every 5 minutes: ``` [2026-03-01 11:00:00 AM] Health check performed - App uptime: 0h 5m (started: 2026-03-01 10:54:37) [2026-03-01 11:00:01 AM] Health check - Hub connected: true, Internet: true ``` Uptime should increment correctly: 0h 5m → 0h 10m → 0h 15m → ... → 14h 0m → 14h 5m ### 5. What You Should NOT See If app stays alive, you should NOT see: - `[onAppPaused]` - means app going to background - `[onAppDetached]` - means app being killed --- ## Expected Timeline | Time | Expected Behavior | |------|------------------| | **First 5 min** | Health check logs start appearing | | **After 1 hour** | Uptime shows ~1h 0m | | **After 14 hours** | ⚠️ **CRITICAL CHECKPOINT** - App should still be running (previously died here) | | **After 24 hours** | Uptime shows ~24h 0m | | **After 48 hours** | Uptime shows ~48h 0m | | **After 60+ hours** | Warning log: "App running for 60+ hours" | --- ## If App Still Dies ### Check 1: Last Logs Before Death Look at last log entry before silence: - If `[onAppPaused]` present → OS killed app (check device settings) - If no lifecycle event → app crashed (check for exceptions) ### Check 2: Device-Specific Settings Some Android devices have aggressive task killers even on AC power: - Check "Auto-start" settings (Xiaomi, Oppo, Vivo) - Check "Background restrictions" in device settings - May need to whitelist app in manufacturer's custom settings ### Check 3: Android Version - Android 6+ has Doze mode even on AC power - Android 9+ has App Standby Buckets - May need ADB commands to whitelist: ```bash adb shell dumpsys deviceidle whitelist +com.example.hmg_qline.hmg_qline ``` --- ## Success Indicators ✅ Health check logs every 5 minutes ✅ Uptime increments correctly ✅ No `[onAppPaused]` or `[onAppDetached]` logs ✅ Hub connection stays alive ✅ App runs past 14-hour mark ✅ App runs 48+ hours without restart --- ## Emergency Rollback If new version causes issues: 1. Keep old APK as backup 2. Reinstall old version via ADB 3. Report issue with last 100 lines of logs