Feature request: Proper background process

I have been using watchfaces for so-called background processing, but there are more and more limitations in which watchface execution is suspended entirely making this less effective, causing gaps in my data.  Previoiusly watchfaces would only be suspended when a widget or activity was active.  Now with new features like the morning report, watchface during sleep, and always on display off option, there are more cases where watchface "background" code (whether run in the background or on 1 min update) is suspended. 

It would be nice to have a way to specify a proper background process with somewhat "guaranteed" execution (and execution time limit of course).  Ideally the execution period could be customized (every 1 min to 60 min).  Perhaps a totally new type of app needs to be invented for this.

  • I'm still tinkering with this as a back burner project.  I'm still not sure it will do what I want in my application.  Since the background process cannot write to Storage, it needs to pass data to the main process once in a while and get it to process it.  Otherwise a lot of data can accumulate over lets say 1-3 days, and probably the app will choke at some point unless the user activates the widget once a day at least.  It looks like the main process only runs (and receives the queued up background data) when the user manually launches the widget.

    Now, I saw a widget that apparently ran in the background, and then launched a notification on my watch with a vibration, putting up a menu that had options like Launch, and Dismiss (I only saw this once so I don't remember clearly).  I was wondering how the heck did he do this?  I can't find anything in the CIQ API docs that would seem to do this.

  • Background.requestApplicationWake() from the background service

  • onBackgroundData frequently doesn't work, and there is a not very clear excuse for this that you have to read into in the documentation. The way I managed to get storage to work between the watchface and background consistently is I created a class that has wrappers for getting and setting storage, annotated the class as :background, and use the same class in the background class as I do in the watchface class. Unless you don't ever use storage for anything else you will probably not want to use onStorageChanged, but instead check the stored data for changes using a flag in the stored data.

  • onBackgroundData won't be called if the background has run more than 30 seconds before BackGround.exit() is called,

    or if you call Background.exit(null).  Say the data you get back from makeWebRequest is null

  • The biggest problem is that if the watchface is in low power mode it also won't get onBackgroundData: From the API docs:

    When the Background process terminates, a data payload may be available. If the main application is active when this occurs, the data will be passed directly to the application's onBackgroundData() method. If the main application is not active, the data will be saved until the next time the application is launched and will be passed to the application after the onStart() method completes

    This is what I saw on a real device through lots of logging. It also turns out onStop isn't always called when the watchface is restarted when the watch switches between day and sleep times which is yet another issue.

  • The watchface is "active" in low power mode if you can see it.

    On some devices, there is a switch to a different (native) WF between sleep and wake times, and your watch face isn't active during those times.  You can't see it.

  • Also, let's say you have two watch faces installed with background services.  The background will only run for the "active" one - the one you see running.  The background for the one you don't see doesn't run.

  • I have a MIP watch so I can always see it regardless of which of onEnterSleep or onExitSleep was called most recently. And yes even if I have a different sleep watch face I can still see it at night. The short answer is don't use onBackgroundData to get data from the background to a watchface and expect it to work reliably. It doesn't help that sim and real watch behavior aren't the same in this case.

  • I've used it in many apps for years and never had an issue with getBackgroundData.

    If you try to return too much in Background.exit(), an exception is thrown in the background service, and onBackgroundData won't be called.  Same as the cases I mentioned where you run more than 30 seconds, or return null.

  • Been tinkering with this again.  I found that the temporal events don't seem to be all that reliable. I set up a one shot temporal event to happen 10 minutes later, then in the onTemporalEvent() handler I did:

            Background.requestApplicationWake("Launch Widget?");
            Background.exit(null);
    And when the user launches the widget I set up the next one shot temporal event to happen 10 minutes later.
    If I'm sedentary, the wake ups happen regularly. But If I'm out walking about, (but not having any activity app active), the wakeups seem to be totally suspended meaning that the onTemporalEvent() callbacks didn't occur.  I guess this is consistent with what you describe "After that, the background service will run when resources are available to do so."   
    The 10 minutes was just a value for testing.
    The problem is that in my widget I want the temporal events to happen once a day, more or less the same time each day, and unless the user happens to launch the widget at around that time, I can't schedule a periodic event, but only a one time event.
    Also if the scheduled temporal event is suspended, it seems lost forever and there is no retry.  Not good for what I'm trying to do unfortunately.