onBackgroundData not called

I searched the forum, and read all the old threads related to onBackgroundData, but I can't find out why it's not working.

(:background)
class MyServiceDelegate extends System.ServiceDelegate {

	function initialize() {
		Background.exit("this works");
	}
	
	function onTemporalEvent() as Void {
		log("onTemporalEvent");
		// Background.exit("test1");
		doTheWork();
		// Background.exit("test2");
	}
}

My problem is that onBackgroundData is not being called after I call Background.exit(non null String or Number); The only place where it works is when I call it from the constructor of the ServiceDelegate, which of course makes no sense, because then the job didn't even start yet, but at least it proves that the onBackgroundData in the foreground app is OK.

When I call Background.exit("str") from anywhere else (my real place is the onReceive callback of makeWebRequest, but even if I call it from the beginning of onTemporalEvent) onBackgroundData is not called. What can be the culprit?

SDK 4.1.7, simulator, fr255, datafield

  • I circumvented this whole system by just using Storage and onStorageChanged.  It works for me, and perhaps it can work for you as a workaround?  Pick a key.  Clear it when you start the background (as double confirmation).  Set it when you're exiting.  Listen for that on the front-end code. If non-null, act on it and clear storage for that key for next time.  

    (This isn't exactly how I do it -- this seems wasteful if you're just trying to message-pass.  In my actual use case, I do require the information to be stored anyway, so it's not wasteful.  But it could create a simple message-passing system, too).

  • Yeah, I also found onStorageChanged yesterday, and thought that maybe I'll use it instead.

  • I still can't fix it. Even when I stripped it down to the bare minimum it doesn't work. I uploaded the minimal project to: https://github.com/flocsy/garmin-onBackgroundData

    The goal: after it logs "Background: Stats.onReceive: Background.exit:" we should see the log: "TestApp.onBackgroundData !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"


    Who can find the problem?

    I did see the onBackgroundData being called once, when there was error -101, which is probably a bug in the simulator, but whenever I get real response or even if I change the hostname to some garbage and receive responseCode 404 it's not being passed back to the foreground app's onBackgroundData method

  • This is a shot in the dark, but I noticed you are calling Background.exit() from another file. 

    I've found that things like this that should work and represent good modular design stretch the limits of what the Garmin team probably envisioned and tested to support.  I'll bet they only thought people would call Background.exit() from inside methods inside the class that extendsSystem.ServiceDelegate. Or if not that, some other weird limitation about where (file-wise) you call Background.exit().

    Consider finding a way to get the Background.exit() call to be made from inside the StatsServiceDelegate class and see if that resolves it?

  • No it doesn't. Even if you look at my original example above you'll see that I added Baxkground.exit to MyServiceDelegate.onTemporalEvent() and it doesn't work even there. But it does work in MyServiceDelegate.initialize().

  • This has me scratching my head.  I wish I could help more.  Next time I get back in code, I'll explore if I can get the onBackgroundData to call reliably

  • import Toybox.System;

    (:background)                    //------>   , :background_app)
    class StatsServiceDelegate extends System.ServiceDelegate {

        function initialize() {
            // TODO: can it be removed?
            ServiceDelegate.initialize();
            log("StatsServiceDelegate.initialize");
        }
        
        function onTemporalEvent() as Void {
            log("StatsServiceDelegate.onTemporalEvent");
            Stats.onTemporalEvent();
        }
    }

    1:29:27 TestApp.initialize: true
    1:29:27 TestApp.onStart: true
    1:29:27 setStorage: Q = s
    1:29:27 Stats.triggerTemporalEvent: 1:27:49, 1:32:49: s
    1:29:27 TestApp.getInitialView
    1:29:27 TestApp.onBackgroundData !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!: -101
    1:29:27 Stats.onBackgroundData: -101
    1:29:27 Stats.onBackgroundData: delete storage
    1:29:27 setStorage: Q = null

    -101 means you put too many webreqs

  • Web request result storage is limited (to 8k I read somewhere?) and it tripped me up. I had to result to implementing a loop by having the onReceive method call the web request again until the end of the list, then I could exit with a "done" status. I added a retry counter in case onReceive got errors so if retry count exceeded I could exit with an "error" status.

  • Not in this case. The respond has a few bytes.