You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_QLine/AC_POWERED_KIOSK_SUMMARY.md

235 lines
6.5 KiB
Markdown

# 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`