Android 10 killing the Hubitat background services every 24 hours

If I don't launch the Hubitat app on my new Android phone which is running Android 10 I never receive any hub notifications. The moment I launch the app the notifications start rolling in. I have been reading how "aggressive" Google has become with Android power management and the options of making sure there are no "background restrictions" and remove the app from optimization haven't worked. The configuration is below:

I will be honest I have see the same behavior with other apps on this new phone such as Tempest notifications, OneDrive photo uploads, and apps that backup my SMS or download Podcasts. They are all exhibiting this aggressive "kill the background worker threads" process. Once you let the app go idle for a few hours Android blocks their background workers.

Does anyone have any idea's on how to resolve this...I have done so much research and have no answers. The app works great on my older phone which is running Android 9.

Huh ... I just realized that I'm experiencing the same with a few work apps. I never put it together that this was happening. Google will get a ton of complaints and fix it. But geesh .. I'll see if I can also research it later. Good catch. I figured it was in my settings somewhere and put off checking.

TL;DR: Your app will always be killed. The app needs to use Firebase Cloud Messaging to ensure timely notifications and need users to interact with them to have tasks run immediately.

Long explanation
I have been doing some android development and so I have learnt a lot about the android platform. You cannot run tasks in the background of Android for long periods of time.

Apps are required to follow job scheduler rules. An app has to wait for the OS to trigger an event, the apps subscribe to those triggers and request jobs to be run. For example, say you arrive home, your phone will know that for numerous reasons (connected to your home wifi, approximate location, etc). The app can then request a task be completed based on that trigger and/or send the user a notification. However, there is no guarantee the app will be able to send the notification immediately. All the apps that want to send notifications get grouped together and sent out periodically to the phone. So instead of your phone sending you 20 notifications every few seconds keeping your phone awake, firebase cloud messaging (FCM) batches them out and sends you 1 or 2 FCMs with each FCM having multiple notifications (gmail, weather, etc). Note this is a gross oversimplification so there are many exceptions to all these.

Say the app wants to do a task that isn't a notification, your phone provides small windows of opportunity where all apps can execute tasks. If the tasks are larger than the window, those tasks are delayed until the next window. The frequency of windows of execution depends on many factors such as how often you turn on your screen, how often you charge your phone and how much you use each app. Apps barely used to run once every 24 hours while highly frequent apps get to run much more often.

So how does an app get to run tasks quickly and often? Become a foreground app which requires user interaction such as opening the app or reacting to a notification in the notification shade. Some apps are exempt in part like text messaging and phone calls since those are high priority but that is baked into the OS.

Yes Android's modern algorithm for running background threads is usage based. I have been in and out of app development since Donut (API 1.6) and was building a cloud music player app as a hobby that would stream audio from home server. Fighting the OS when the app would go into background was something I had to account for back then. Single threading was the issue.

It is thread pooling that separates the background threads from the "main" thread. You have to declare your application as functional components, One such component is classified as "Application" which is the main thread and handles UI, and the others such as "Service" is where the event listener should be initiated.

Programming android today requires a large investment in understanding the process model and with Google constantly changing the rules between API versions is one reason I don't go there anymore and why the company I work for now invests in a 3rd party framework to manage application complexities.