Summary
Battery level notifications (warning / critical / full) only fire while the app is open in the foreground. As soon as the app is closed or backgrounded, monitoring stops and no alerts are delivered. There is also no persistent, ongoing battery-status notification like AccuBattery's.
Root cause
The only thing that listens for ACTION_BATTERY_CHANGED is BatteryLevelReceiver (+ PowerConnectionReceiver). These are not declared in the manifest — ACTION_BATTERY_CHANGED is a sticky broadcast that cannot be registered in AndroidManifest.xml and must be registered at runtime against a live Context.
They are registered at runtime inside PowerConnectionService:
app/src/main/java/.../service/PowerConnectionService.java:48-60 registers both receivers in onCreate().
app/src/main/java/.../ui/MainActivity.java:143 starts the service with startService(...).
But PowerConnectionService is a plain background Service — it never calls startForeground(), and the manifest declares no FOREGROUND_SERVICE permission or foregroundServiceType. On Android 8+ (this app is minSdk 26), the OS stops background services and reaps the hosting process within minutes of the app leaving the foreground. When the service is destroyed, onDestroy() unregisters the receivers (PowerConnectionService.java:65-83), so battery broadcasts stop arriving and no notifications are sent.
onStartCommand returns START_STICKY (PowerConnectionService.java:40-42), but on modern Android a backgrounded sticky service is not promptly (or reliably) restarted, and even if it were, onStartCommand does not re-register the receivers — only onCreate does.
This is also why charge cycles never increment / health stays at 100% (see the separate health-tracking issue): BatteryHealthTracker.recordBatteryState() is only called from BatteryLevelReceiver.onReceive, which is effectively only alive while the app is open.
Why "not sticky like AccuBattery"
AccuBattery's always-present notification is a foreground-service ongoing notification showing live battery %. This app has no such notification. The _pref_key_notifications_sticky preference only adds FLAG_NO_CLEAR/FLAG_ONGOING_EVENT to alert notifications (NotificationService.buildNotification, line ~328) and defaults to false — it is not a persistent live-status notification.
Proposed fix
Convert PowerConnectionService into a foreground service:
- Add permissions:
FOREGROUND_SERVICE and an appropriate FOREGROUND_SERVICE_* type. A battery monitor most closely fits specialUse (requires a Play Console declaration) or systemExempted; evaluate per Android 14+ rules.
- Declare
android:foregroundServiceType on the <service> in the manifest.
- Call
startForeground(id, ongoingNotification) from the service, with a low-importance ongoing notification that shows live battery % (this doubles as the AccuBattery-style persistent notification users are asking for, and keeps the process alive so monitoring continues).
- Start it via
startForegroundService(...) from MainActivity and from boot (see the boot auto-start issue).
- Re-register receivers defensively in
onStartCommand (or keep them registered for the service lifetime).
Acceptance criteria
- Battery warning/critical/full notifications fire with the app closed.
- A persistent ongoing notification shows the current battery % and updates over time.
- Monitoring survives the app being swiped away and resumes after reboot.
Summary
Battery level notifications (warning / critical / full) only fire while the app is open in the foreground. As soon as the app is closed or backgrounded, monitoring stops and no alerts are delivered. There is also no persistent, ongoing battery-status notification like AccuBattery's.
Root cause
The only thing that listens for
ACTION_BATTERY_CHANGEDisBatteryLevelReceiver(+PowerConnectionReceiver). These are not declared in the manifest —ACTION_BATTERY_CHANGEDis a sticky broadcast that cannot be registered inAndroidManifest.xmland must be registered at runtime against a liveContext.They are registered at runtime inside
PowerConnectionService:app/src/main/java/.../service/PowerConnectionService.java:48-60registers both receivers inonCreate().app/src/main/java/.../ui/MainActivity.java:143starts the service withstartService(...).But
PowerConnectionServiceis a plain backgroundService— it never callsstartForeground(), and the manifest declares noFOREGROUND_SERVICEpermission orforegroundServiceType. On Android 8+ (this app isminSdk 26), the OS stops background services and reaps the hosting process within minutes of the app leaving the foreground. When the service is destroyed,onDestroy()unregisters the receivers (PowerConnectionService.java:65-83), so battery broadcasts stop arriving and no notifications are sent.onStartCommandreturnsSTART_STICKY(PowerConnectionService.java:40-42), but on modern Android a backgrounded sticky service is not promptly (or reliably) restarted, and even if it were,onStartCommanddoes not re-register the receivers — onlyonCreatedoes.This is also why charge cycles never increment / health stays at 100% (see the separate health-tracking issue):
BatteryHealthTracker.recordBatteryState()is only called fromBatteryLevelReceiver.onReceive, which is effectively only alive while the app is open.Why "not sticky like AccuBattery"
AccuBattery's always-present notification is a foreground-service ongoing notification showing live battery %. This app has no such notification. The
_pref_key_notifications_stickypreference only addsFLAG_NO_CLEAR/FLAG_ONGOING_EVENTto alert notifications (NotificationService.buildNotification, line ~328) and defaults tofalse— it is not a persistent live-status notification.Proposed fix
Convert
PowerConnectionServiceinto a foreground service:FOREGROUND_SERVICEand an appropriateFOREGROUND_SERVICE_*type. A battery monitor most closely fitsspecialUse(requires a Play Console declaration) orsystemExempted; evaluate per Android 14+ rules.android:foregroundServiceTypeon the<service>in the manifest.startForeground(id, ongoingNotification)from the service, with a low-importance ongoing notification that shows live battery % (this doubles as the AccuBattery-style persistent notification users are asking for, and keeps the process alive so monitoring continues).startForegroundService(...)fromMainActivityand from boot (see the boot auto-start issue).onStartCommand(or keep them registered for the service lifetime).Acceptance criteria