onBackgroundData not called from when Background.exit is called from makeWebRequest callback

Hi, I am working on a background web request for a watch face.  I have read various discussions here on this but nothing that solves my issue.

I include full test code simplified as far as possible (it's only 90 lines) - when the temporal event is fired in the simulator the web request is made and successfully returns a result.  When Background.exit is then called, onBackgroundData is not called.

I thought it easier to show the full code rather than explaining further what I do and don't do.  As a test line 74 can be uncommented (this does fire onBackgroundData, but without the web request result so is useless) I am using VSCode.

Thanks for any insights anyone may have...

Full file litdev.uk/stuff/bgwfApp.mc - can't update in this slightly weird forum.

MonkeyC.txt
using Toybox.Application as App;
using Toybox.Background;
using Toybox.System as Sys;
using Toybox.WatchUi as Ui;
using Toybox.Graphics as Gfx;
using Toybox.PersistedContent;
using Toybox.Lang as Lang;

var inBackground = false;
var _myResult = -1;

(:background)
class bgwfApp extends App.AppBase {
  function initialize() {
    AppBase.initialize();
  }

  // onStart() is called on application start up
  function onStart(state) {
    Sys.println("onStart");
  }

  // onStop() is called when your application is exiting
  function onStop(state) {
    if (!inBackground) {
      Sys.println("onStop !inBackground");
    } else {
      Sys.println("onStop");
    }
  }

  // Return the initial view of your application here
  function getInitialView() {
    Sys.println("getInitialView");
    if (Toybox.System has :ServiceDelegate) {
      Background.registerForTemporalEvent(new Time.Duration(5 * 60));
    } else {
      Sys.println("****background not available on this device****");
    }
    return [new bgwfView()];
  }

  function onBackgroundData(data) {
    Sys.println("onBackgroundData=" + data);
    _myResult = data;
    Ui.requestUpdate();
  }

  function getServiceDelegate() {
    Sys.println("getServiceDelegate");
    return [new BgbgServiceDelegate()];
  }

  function onAppInstall() {
    Sys.println("onAppInstall");
  }

  function onAppUpdate() {
    Sys.println("onAppUpdate");
  }
}

(:background)
class BgbgServiceDelegate extends Toybox.System.ServiceDelegate {
  function initialize() {
    Sys.ServiceDelegate.initialize();
    inBackground = true; //trick for onExit()
  }

  function onTemporalEvent() {
    getMyData();
    Sys.println("onTemporalEvent");
    _myResult = 0;
    //Background.exit(_myResult); // This fires onBackgroundData, but obviously doesn't do the web request!
  }

  private function getMyData() as Void {
    var options = {
      :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON,
      :headers => {
        "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED,
      },
    };
    Communications.makeWebRequest(
      "https://jsonplaceholder.typicode.com/todos/115",
      null,
      options,
      method(:onReceive)
    );
  }

  • can't past the code here

    The forums have been broken for almost half a year (not just a couple of days or weeks), when it comes to pasting certain permutations of text, code, images, and links. Garmin is well aware of the problem, but since they managed to fix it for most of the "normal" forum users (i.e. not developers), and since there's no reliable way to trigger these bugs (except maybe by making super long posts / pasting lots of code), I don't think the problem is ever getting fixed.

  • Does this impact in my original question - I have exactly the same issue if I delete all global variables completely.

    Yeah I figured that _myResult has nothing to do with the problem, but so far I don't see anything else that's out of the ordinary.

    Which SDK are you testing with? I assume you're testing in the simulator? Which (simulated) device are you testing on?

    I'll try your code in the sim and see if I have the same problem.

    EDIT: I see the exact same thing with SDK 8.1.1, fr955 (sim).

    I also see the problem with SDK 7.4.3, fr935 (sim), so it doesn't seem to be some sort of new SDK bug

  • Thanks for reply - I did the Background.Exit(1) when I tested with _myResult deleted just now - onBackgroundData is not called when Background.exit is called from web request response - regardless of arguments, onStop is called as you can see in my print log.

    I can debug with break points in VSCode and see all values as expected apart from onStop is called, not onBackgroundData.

    It's a simple code, perhaps someone could run it - I would be surprised if this stuff just doesn't work, but I don't see any working examples either.  As far as I can see the webrequest access samples that come with SDK either don't run as background process or just send the Background.exit command directly from 
    onTemporalEvent which does make me slightly suspicious.

     

  • Thanks for taking the time to test.

    I tried a couple sim devices all the same issue, currently D2 Mach 1 using SDK 8.1.0.

    As I say I can't believe it doesn't work, but the code is pretty simple and there doesn't seem to be a working sample I have been able to find and plenty of inconclusive questions about it.


  • I don't see any working examples either

    There have been several working examples posted in the forums, and there are lots of watchfaces in the CIQ which request data in the background and display it on the watchface. Something very strange is going on here (not to state the obvious).

  • I remember about 2 years ago I also tried to make this work, and then I gave up. So it's not that trivial.

  • It looks straightforward, I can't believe there isn't a trick to it - there seems to be no other way to store or pass data between background and foreground apart from Background.exit which doesn't seem to work with webrequest response - strange.

    Thanks for your time!

    Maybe has some idea, following his initial post noting my failure to post the full code properly.

  • Not sure exactly where the bug in your code is, but trust me, a background service with makeWebRequest works and I've been doing it for years.

    Couple notes,  if you do Background.exit(data) where data==null, onBackground data in the main app won't be called, or if it takes longer than 30 for the background to run and get a response, the background will be terminated before Background.exit is called and onBackgroundData isn't called.

    I'll take a look at your code when I got a bit of time...

  • Thanks for your reply - I had seen both these caveats in your posts on this forum and that you have been using it for years so presumably it does work without some undocumented magic.  That's why I simplified the code as far as I could before posting my question - the code is very simple - no null data and certainly way less than 30 sec.

  • I remember about 2 years ago I also tried to make this work, and then I gave up. So it's not that trivial.

    Yeah, I'm re-reading your thread now.

    Gotta love the constant sense of deja vu that comes with CIQ development

    https://forums.garmin.com/developer/connect-iq/f/discussion/324155/onbackgrounddata-not-called/1572621#1572621

    From further investigation it looks like this doesn't work in exactly the scenarios that I use: when in the background app I send a web request (either from "Background"AppBase.onAppUpdate or ServiceDelegate.onTemporalEvent) and I want to wait for the response (who doesn't want?) and so I only call Background.exit from the onReceive callback of Communications.makeWebRequest, THEN "Foreground"AppBase.onBackgroundData isn't called.

    I am sure that there's something I don't do right, or I don't understand how this is supposed to work, because in my mind the only reason for having Background.exit in the SDK is to let the background app wait for the webrequest's response, and only stop the background app after the response is received AND pass the data back to the foreground app.

    No, pretty printer is not involved, I am testing it in the simulator on fr255, with the regular garmin compiler only, no optimization.