How to use background annotations

I did not find any docs for this, all I can find is examples and some posts here.

My deductions are following:

(:background)

Used to annotate a class. It says that the class is known and accessible in background as well.

(:background_method)

Used to annotate a function that is known and accessible in background

Is this true so far?

Questions:

  • Do I need to annotate ANY function inside a class with the (:background_method) annotation if it is used in the background? Additionally, is the (:background_method) annotation only valid inside a class annotated with (:background)?
  • How can I access static const fields in the background? I added an example code below which does not work (accessing both fields from the background result in "Error: Illegal Access (Out of Bounds) Details: Failed invoking <symbol>" error...

(:background)
class Constants {
	
    static const PROP_PENDING_WEB_REQUEST = "PendingWebRequests";
    
	(:background) static const PROP_PENDING_WEB_REQUEST2 = "PendingWebRequests";

}

  • I've never seen any reference to a (:background_method) annotation, just (:background).

    When you use (:background) it's for the whole code block, so in your code above, you shouldn't need the annotation on line 6.

    What's the stack trace where you get the illegal access?

    Given that, I tried this:

    module BgWu {
    	(:background)
    	class Constants {
    	
       		static const ABC = "PendingWebRequests";
        
    		(:background) static const XYZ = "PendingWebRequests2";
    	}
    
    	(:background)
    	class WuServiceDelegate extends Sys.ServiceDelegate {
    
    	    function initialize() {
    	    	ServiceDelegate.initialize();
    Sys.println("abc="+Constants.ABC+" xyz="+Constants.XYZ);
            }
        }
    }

    with no problem.  Moving Constants outside the module also worked fine.

    Are you by any chance trying to use resources in the background?

  • I've seen the (:background_method) in an open source app... But good to know that you only need to annotate the class itself - tested this and you're right, thanks for this.

    Regarding the static const fields, my class contains arrays of resources like following:

    (:background)
    class Constants {
    	
    	static const TIME_FORMAT_NORMAL = 1;
    	static const TIME_FORMAT_MILITARY = 2; 
    	
    	// --------------
    	// internal properties
    	// --------------
    
    	static const PROP_PENDING_WEB_REQUEST = "PendingWebRequests"; 
    	// ...
    	
    	// --------------
    	// Keys (HashMaps)
    	// --------------
    	
    	static const KEY_ERROR = "httpError";
    	// ...
    	
    	// --------------
    	// Arrays
    	// --------------
    	
    	static const WEEK_DAYS = [
    		Rez.Strings.Sun,
    		Rez.Strings.Mon,
    		Rez.Strings.Tue,
    		Rez.Strings.Wed,
    		Rez.Strings.Thu,
    		Rez.Strings.Fri,
    		Rez.Strings.Sat
    	];
    	
    	// ...
    }

    I do not access the resources in the background - still, could it be that using the resource identifiers in the background already makes problems?

    Regarding the stacktrace for the illegal access exception - it's just one line and points to weird positions. I tried to get it again and it points to a function that is never called, namely Props.delete. Here's the source code that already triggers this exception:

    (:background)
    class BackgroundService extends System.ServiceDelegate {
    
    	// ...
    	
    	function onTemporalEvent() {
    	
    		Debugger.logFunction(BackgroundService.DEBUG, "BackgroundService", "onTemporalEvent");
    		
    		var propPendingWebRequest = Constants.PROP_PENDING_WEB_REQUEST;
    		
    		var pendingWebRequests = Props.get(propPendingWebRequest);
    		
    		// THIS never called if I use Constants.PROP_PENDING_WEB_REQUEST, but everything works
    		// if I set propPendingWebRequest to the string directly!
    		Debugger.logFunction(BackgroundService.DEBUG, "BackgroundService", "Props.get(propPendingWebRequest) called");
    	}
    }
    
    // Props class extract
    
    (:background)
    class Props {
    
    	// ---------------
    	// fields
    	// ---------------
    	
    	static const COLOR_FOREGROUND = "ForegroundColor";
    	static const COLOR_BACKGROUND = "BackgroundColor";
    	static const COLOR_ACCENT = "AccentColor";
    	
    	// few more fields
    	// ...
    	
    	// ---------------
    	// functions
    	// ---------------
    
    	function get(key) {
    		return Application.getApp().getProperty(key);
    	}
    	
    	function set(key, value) {
    		Application.getApp().setProperty(key, value);
    	}
    	
    	function delete(key, value) {
    		Application.getApp().deleteProperty(key);
    	}
    	
    }

  • If you check the programmer's guide, you see that (:background_method) isn't standard, though it could be use defined,

    Couple of things with your code.  "Rez" is likely your problems, as things like strings need to be scoped to use them in the background or glances.  Again, in the programmer's guide, the section called "Resource Scopes".  Here's the simple example from there.

    <resources>
        <string id="MyBackgroundString" scope="background">Background String</string>
        <string id="MyGlanceString" scope="glance">Glance String</string>
        <string id="MyForegroundString" scope="foreground">Foreground String</string>
    </resources>

    Memory can be tight for a background (28k on many devices) so you may want to be careful what you have in the background as far as code, etc, you don't need in the background.

    The other thing, is in the background you can only read properties and storage - not write them, delete them, etc. so your set() and delete() functions can not be called from the background.

  • Another note about memory.  When you have backgrounding your AppBase is always included in the background, so that takes memory, and if you are doing makeWebRequest calls, that can take more memory that you things.  The jso data you get has to be converted to a dictionary, so there's memory used there, and as a dictonary, it will take more memory than if  it was just "flat" data.

    Here's a thread from a few years back that's about backgrounding that started back when it was first introduced: https://forums.garmin.com/developer/connect-iq/f/discussion/5287/very-simple-sample-of-a-watch-face-with-a-background-process

    for WEEK_DAYS, not sure how you're using that, but using FORMAT_MEDIUM with Time.Gregorian.Info, you get those names using the FW strings vs having your own, so can save some memory in general..  If the watch is set for French, you'll get the day names in French

  • Resources in background

    You were right. It seems, using the resource ids in background already makes problems. I thought it's only problematic to load them in the background and was not aware of that even using their definition ids makes problems... I don't need any resources in the background - so I now split up the constants file and moved the resource arrays to a different file and now it works fine.

    Write/Delete properties

    I don't do this in the background but the functions do fit into this class... But thanks for making this clear.

    Memory

    Thanks for your hint about the Gregorian.Info. I checked this and I saw, that I can get weekday names + month names by it. I will use them in the future.

    EDIT: I tested the Gregorian.Info in the emulator - it seems to return english strings always

  • The sim only supports a few languages right now.  Try French, Spanish or German as I think one of those is supported.

    Ad far as the write/delete, one think to keep in mind is things in AppBase may run when you don't expect with a background.  For example, initialize(), onStart() and onStop() all run each time the background runs as part of the background.

  • Seems like the emulator only supports english... But tried it on my device and everything is working fine. Thanks for all your feedback and tipps.

  • Actually, Simplified Chinese works in the sim

  • True, simplified chinese works.