6.5 KiB
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:
- Android treats long-running apps as "idle" even on AC power
- No user interaction for extended periods
- Android's background task restrictions kicked in
- 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:
// WRONG - calculated time since last MIDNIGHT, not app start
DateTime.now().difference(lastChecked).inHours
Solution:
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.xmlandroid/app/src/main/kotlin/.../MainActivity.kt
Changes:
- Added window flags to prevent sleep/idle:
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)
}
- Added activity flags in manifest:
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
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:
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
- ✅
lib/view_models/screen_config_view_model.dart - ✅
lib/models/global_config_model.dart - ✅
lib/repositories/signalR_repo.dart - ✅
android/app/src/main/AndroidManifest.xml - ✅
android/app/src/main/kotlin/.../MainActivity.kt - ✅
CHANGES_EXPLANATION.md(full documentation)
Next Steps - Deploy & Test
1. Build APK
cd /Volumes/Data/Projects/Flutter/HMG_QLine
flutter clean
flutter build apk --release
2. Deploy to Test Device
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:
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:
- Keep old APK as backup
- Reinstall old version via ADB
- Report issue with last 100 lines of logs