Background activity calculation

Hello,

Thanks to  thread about background activity (this -very nice- one: https://forums.garmin.com/developer/connect-iq/f/discussion/5287/very-simple-sample-of-a-watch-face-with-a-background-process ) I added some Sun Events and Weather calculation to my watch face, all calculated only one to four times an hour rather than each second (!)

BTW it sometimes happens that no data is available and I don't know why / in what circumstances. Here is the ServiceDelegate class:

function onTemporalEvent() {

    var data = new[5];

    /! Weather data calculation    

    if (Weather.getHourlyForecast() != null) {

        data[0] /* weatherIcon */ = whatIcon(Weather.getHourlyForecast()[2].condition);

        (...)

    }

    else {

        data[0] /* weatherIcon */ = "@";

         (...)

    }

    //! Next sun event calculation

    data[3] = getSunValue();

    //System.println(sunEventHour.substring(0,2));

    if (data[3] != "n/a") {

        if (data[3].substring(0,2).toNumber() < 12) { //set sunrise icon

           data[4] /* sunEventIcon */ = ">";

        }

        else { // set sunset icon

           data[4] /* sunEventIcon */ = "?";

        }

   }

   Background.exit(data);

}

And here is the App part:

function onBackgroundData(data) {

   // Saving background data

  if (data[0] != null) {

     weatherIcon = data[0];

     Application.getApp().setProperty("weatherIcon",data[0]);

  }

  // Else reading cached data

  else {

     if (Application.getApp().getProperty("weatherIcon") != null) {

        weatherIcon = Application.getApp().getProperty("weatherIcon");

     }

     // Else default value

     else {

        weatherIcon = "@";

     }

  }

   (...)

  WatchUi.requestUpdate();

In the View part I use weatherIcon (and other set in App) variable to display data. This variable is global and initialized with "". Is there something I am doing in a wrong way? Thanks for your help 

  • Use .equals rather than == with string.

    EG:

    if(myStr.equals("testStr")) {
        // Do something...
    }

  • Thanks @9635560 will do that. Could it actually be the root cause of these empty data ?!

  • Well, anywhere you are testing the contents of a string, you will get unexpected results... 

    var myStr = "bob";
    
    // THIS WILL GIVE YOU EXACTLY THE WRONG RESULT!
    if(myStr == "bob") {
        System.println("bob is what the string is");
    } else {
        System.println("The string is completely devoid of bobs");
    }
    
    // THIS WILL GIVE YOU EXACTLY THE RIGHT RESULT!
    if(myStr.equals("bob")) {
        System.println("bob is what the string is");
    } else {
        System.println("The string is completely devoid of bobs");
    }

    So if you are testing for "n/a" like this:

    if (data[3] != "n/a") {

    Well...

    If you do it once, then (like I did) you'll probably have done it lots of places and then spent lots of time scratching your head and feeling stupid.

    I don't know where your data is showing empty, but it is certainly a definite, known, problem that will give you what you don't want.

  • I am surprised it could be so important (!) I've been testing strings this way for... a long time. Thank you I changed all my string tests (and I have to do so in my other WF !!!)

    Unfortunatly the problem is still there. I actually get empty data, not "n/a" which occurs when weather or sunevent can not be calculated. It is just like if the variables were reseted / the app restarted.

  • Using == on strings compares the objects, while equal() compares the the strings in those objects.

    when you say "no data is available" are you sure the background has run?  On a real device for example, the background won't run while you are running a CIQ device app.  While with a native activity, the background can run multiple times before the watchface runs at all.  Using getBackgroundData in your background allows you to append new data to what hasn't been seen in onBackgroundData in the main app.

  • Thank you for this new answer. I will try to be more precise so that we can help me.

    I know that background has run since variables (there are 5 fields calculated and then displayed in onUpdate(dc) ) set in onBackgroundData() actually get the info I am looking for after a few minutes, Whereas these variables are set to "" in onLayout(dc) (everything done in class MyAppView extends WatchUi.WatchFace). So nothing is displayed until the first Temporal Event is thrown.

    And "sometimes" these variables are set back to "" (which is not part of my code 100% sure ; like if onLayout(dc) was called again) and display is then empty for X minutes.

  • hi, do you "store" the data from the background?

    I mean on real device, when you receive for example a notification, when you get back from it, onLayout is called etc.

    I mean you should set your Var in onUpdate, not on onBackgroundData.

    this part:

    if (Application.getApp().getProperty("weatherIcon") != null) {
    
            weatherIcon = Application.getApp().getProperty("weatherIcon");
    
         }
    
         // Else default value
    
         else {
    
            weatherIcon = "@";
    
         }

    should be done in onUpdate or onLayout.

    because if you have onLayout(dc){weathericon="";}

    everytime you will go on widget / app or receive a notification it will be set to ""

  • Confirmed: that was basicly it! What a shame, sorry for disturbing everyone with such a question. I really need to set up a test workflow as close to reality as possible (i.e. including notifications!)

    Thank you all for helping, really appreciated.