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.
235 lines
6.5 KiB
Markdown
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`
|
|
|