Acknowledged

Watchface with a HTTP background process seems to not work properly anymore

A watch face uses a background process to send an HTTP request and retrieve the resulting data in the onBackgroundData function. It always worked fine, until a few days ago.

Indeed, it seems that since the arrival of the 4.2.x versions of the SDK, and the update of the firmware of the watches compatible with these new 4.2 versions, this process in the background no longer seems to work correctly.

For test purposes, I used the small program developed by jm_58, to see what happened, knowing that his program used to work very well with versions 4.1.x of the SDK.

Keeping the code as it is, with version 4.2.3, the program still works very well, the onBackgroundData function is well executed every 5 minutes. But, when I add the code that sends an HTTP request to a server, the problems begin:

- the raw data set is indeed recovered by the code (function onReceiveData(responseCode as Number, data as Dictionary<String, Object?> or String or Null) as Void, the array contains the expected data

- but, when calling Background.exit(data);, the onBackgroundData(data as Application.PersistableType) as Void function is never executed, even after waiting for several minutes, and several reiteration of the request

- the onUpdate function of the View file does not seem to be called either (a breakpoint placed on this line is never executed), we can no longer trace the code

- after a few moments, all the menus of the simulator become grayed out, no access to anything, except the File menu, we are then obliged to force the closing of the simulator, which no longer closes normally by File -> Exit

Finally, I end up with a table containing raw data, which I can no longer use and display on the screen after processing. The problem is that this malfunction also seems to occur on physical models (three users have informed me of this anomaly, the watch face no longer updates with the data, even after uninstalling-reinstalling the application).

I tried to go back, with a lower SDK version (4.1.7) but, unfortunately, it is no longer possible to compile for recent models with a version lower than 4.2.0. So I'm stuck, having found no viable solution to work around the problem (storing the raw dataset on disk then loading the array in the onUpdate) but, again, it doesn't work, going through the function onBackgroundData seems mandatory, but what do you do when this function no longer seems to be called by the system after executing and sending an HTTP request receiving a set of data?

I specify here that the data set never exceeds 8 Kb (we are more on 2-3 Kb), and that the problem exists on several models tested, with always the same symptoms (Epix 2, Fenix 7X, FR965, Venu 2 More in particular), suggesting that this is more a malfunction in the background task process rather than related to a particular model.

I think i have tried everything i could, without success, which is why i am reaching out here, hoping for some insights or suggestions, or a solution to help me out.

Thanks in advance.

Environment: Visual Studio on Mac

SDK version: 4.2.3

  • Thanks jim for your response.

    The makeWebRequest() function seems to be executed correctly because the onReceiveData function receives the code 200, with the array containing the expected data. It's after that things get complicated...

    The code returns to the onStop() function, but never without going through the onBackgroundData(data) function and there, the simulator freezes.

    Here is the result:

    - simulator with all menus grayed out (except the File menu)

    - the onUpdate() function of the View() module is no longer updated (time at which the request was sent = 11:41, system time = 12:05

    - no error code reported in the console log, nothing

    - and of course, the request data cannot be processed or displayed on the screen

    The problem is that this strange behavior (which I have never seen until now) seems to occur on user watches as well. I admit I don't understand anything anymore, it was working very well until recent firmware updates, and switching to SDK version 4.2.x

    It's very similar to the problem Gavriel had, mentioned by his post, but I really don't see what to change to make it work.

  • What might be happening is that your background code is crashing, but you're not seeing the crash in the VSC console.  I've seen that a few times.  This is a case where it might be worth trying a sideload and doing some println() logging and checking the ciq_log file on the device.

    My own apps that have a background service that does makeWebRequest calls work fine with the 4.2.3 SDK.

  • thanks for your feedback flocsy. 

    I am quite ready to accept that the code may contain a bug however, it has always worked until now, since December 2021, which is why I do not understand why it would no longer work today, except if something changed elsewhere...

    As per your request, here the code involved:

    //----------------------------------------------------
    // application file
    //----------------------------------------------------
    using Toybox.Application as App;
    using Toybox.Background;
    using Toybox.System as Sys;
    using Toybox.WatchUi as Ui;
    using Toybox.Time as Time;

    // info about whats happening with the background process
    var counter=0;
    var bgdata="none";
    var canDoBG=false;
    var inBackground=false; //new 8-27
    // keys to the object store data
    var OSCOUNTER="oscounter";
    var OSDATA="osdata";

    (: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) {
    //moved from onHide() - using the "is this background" trick
    if(!inBackground) {
    Sys.println("onStop counter="+counter+" "+ts);
    App.getApp().setProperty(OSCOUNTER, counter);
    } else {
    Sys.println("onStop");
    }
    }

    // Return the initial view of your application here
    function getInitialView() {
    Sys.println("getInitialView");
    //register for temporal events if they are supported
    if(Toybox.System has :ServiceDelegate) {
    canDoBG=true;
    Background.registerForTemporalEvent(new Time.Duration(5 * 60));
    } else {
    Sys.println("****background not available on this device****");
    }
    return [ new bgwfView() ];
    }
    // THIS FUNCTION IS NEVER CALLED THEN, A FEW MOMENT LATER, THE SIM FREEZES (ALL THE MENUS ARE GRAYED, EXCEPT THE FILE MENU)... AND NOTHING MORE HAPPENS
    function onBackgroundData(data) {
    Sys.println("backgroundData= " + data);
    Ui.requestUpdate();
    }

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

    //----------------------------------------------------
    // background file
    //----------------------------------------------------
    using Toybox.Time.Gregorian as Calendar;

    import Toybox.Background;
    import Toybox.Position;
    import Toybox.Communications;
    import Toybox.System;
    import Toybox.Lang;
    import Toybox.Time;

    // The Service Delegate is the main entry point for background processes
    // our onTemporalEvent() method will get run each time our periodic event
    // is triggered by the system.

    (:background)
    class BgbgServiceDelegate extends Sys.ServiceDelegate {
    function initialize() {
    Sys.ServiceDelegate.initialize();
    inBackground=true; //trick for onExit()
    }
    function onTemporalEvent()
    {
    makeWebRequest(); // fonction locale
    }

    // receiving the data from StormGlass or WorldTides
    function onReceiveData(responseCode as Number, data as Dictionary<String, Object?> or String or Null) as Void
    {
    if (responseCode == 200) {
    data.remove("meta");
    Background.exit(data);
    } else {
    Background.exit(responseCode);
    }
    }

    // exécution de la requête web
    function makeWebRequest() {
    if (Sys.getDeviceSettings().phoneConnected) {
    url = "the request sent to the web";

    var params = {};
    var options =
    { // set the options
    :method => Communications.HTTP_REQUEST_METHOD_GET,
    :headers => { "Content-Type" => Communications.REQUEST_CONTENT_TYPE_URL_ENCODED },
    :responseType => Communications.HTTP_RESPONSE_CONTENT_TYPE_JSON
    };

    Communications.makeWebRequest(url, params, options, method(:onReceiveData));
    }
    }
    }
  • I'm not convinced. You say that the original code by Jim works, but when you add your http code to it it doesn't. This sounds like a bug in your code. Maybe you should post your code.

    I'll add that about 2 months ago I had similar problems IMHO still with SDK 4.1.7, you can also find a long thread about it in the forum: forums.garmin.com/.../onbackgrounddata-not-called