Sunday, April 14, 2024

Updating Healthy Battery Charging to Android API level 34

To prolong your Li-ion battery life, reduce e-waste, conserve rare minerals, prevent child labor, i.e. contribute saving the planet - or to save own money if it rings more with you, keep it charged between 40% and 80%, all the time. 

(Technical details about Li-ion batteries are available at the following link: BU-808: How to Prolong Lithium-based Batteries.)

I discovered these facts in 2017, and that's when I published a small Android app that alerts me when it's the right time to connect/disconnect the charger. Healthy Battery Charging was just a minimum viable product, a tool for my own use. I never planed to monetize it, so I released it as a free app, without ads, and I never updated it since.

Fast forward to the year 2024, I have decided to revisit the app, just for the sake of refreshing my knowledge about the way Android handles notifications. A lot of things changed over the years, and I ended up almost rewriting the complete app. And redesigning it, since I am already investing my time.

I've decided to utilize this blog post to track my own design updates and organize my thoughts around notification handling on android. So here we go ...

UI Updates

Launch icon before
Launch icon after
Feature graphic before


Feature graphic after


Screenshot before

Screenshot after

Not sure about you, but I can notice the difference in my own design skills after taking a UX/UI course. 😉

Technicalities

The app schedules a background repeating alarm to check battery and power connection status. The alarm repeats every 15 minutes, though all alarms on android are now inexact and the alarm can be batched with other alarms and triggered later, for example when the device wakes up from the sleep. But for this use case, an exact alarm isn't necessary.

There are situations where pausing the repeating alarm would make sense - once the notification is displayed to the user, it's not necessary to check the status again until the charger is connected/disconnected. The previous app version used to work this way - it had a receiver registered for android.intent.action.ACTION_POWER_CONNECTED and android.intent.action.ACTION_POWER_DISCONNECTED. However, starting from API level 26, these events are not broadcasted to receivers running in the background [docs, exceptions]. They are still broadcasted to foreground services.

When targeting API level 34 or higher, all foreground services must be declared with their service types using android:foregroundServiceType. Currently, the specialUse type seems most suitable for this use case. Additionally, you need to request FOREGROUND_SERVICE permission

Furthermore, apps targeting API level 31 or higher can't start foreground services while running in the background, except for a few special cases.

To maintain the same functionality, a foreground service needs to be started from the boot receiver. The service would need to permanently display a notification. It would not be possible to dismiss it (no notification = no service running), so perhaps it would just change it's text from "Monitoring the battery" to "Connect/Disconnect the charger". I find a permanent notification a bit too much for an app that is supposed to silently run in the background and be invisible most of the time. 

For this reason, at the moment I am preferring the simple approach:

  • Do not pause any alarms and keep them running every 15 minutes. 
  • Do not display notification if it hasn't been previously dismissed. 
  • Dismiss the notification on the next alarm run if the charger has been connected/disconnected. As previously described, notifications can not be dismissed automatically.

Other relevant questions and answers on StackOverflow:
How to listen for power connected Android > 8
How to check which notifications are active in status bar in Android Dev?
Android - AlarmManager is not working after app is closed


https://developer.android.com/reference/android/content/pm/ServiceInfo?hl=en#FOREGROUND_SERVICE_TYPE_SPECIAL_USE
https://developer.android.com/reference/android/content/pm/ServiceInfo?hl=en#FOREGROUND_SERVICE_TYPE_SPECIAL_USE

No comments:

Post a Comment