VERY Simple sample of a watch face with a background process.

This one really doesn't do much. It displays the time, an indication if it's on a device that supports background processes (you can see how that's checked in the App Class), The count of the times the background process has run, and the data returned from the background. It does cache data in the object store, so after the first time the background runs, it will have data.


The background process is a Temporal event, and runs every 5 minutes. All the background does is return a string with a time stamp (HH:MM). There are a number of Sys.println() calls to see what's going on. If you have a watch that supports background processes (f5's,chronos,935,735,va-hr), create a <myapp>.txt in logs to catch the println() calls, as you see kind of a neat thing where those that come from the background are marked as such!

This runs in the sim can you can use the code to build a sideload. In addition to devices that support background processes, I included the fenix 3 as a target so you can see how it works on a watch that doesn't.

if you have questions about the code, just ask!
  • I designed a widget and implemented background services. First of all I am wondering why we have to declare the base app with (:background). I understood that this it the default anyway.

    Next I declared the service:
    function getServiceDelegate(){
    //var ts=now.hour+":"+now.min.format("%02d");
    System.println("getServiceDelegate: ");
    return [new BgServiceDelegate()];
    }


    Saying this I never saw the print out, neither during loading the widget into the simular nor during unload.

    Next I registered for a temporal event in the widget's base app:

    function onStop(state) {
    if(Toybox.System has :ServiceDelegate) {
    //canDoBG=true;

    // delete Background Service if [0] is not today or if an even number of timestamps
    var ts = ttModel.timeStamps[0];
    if ( (!ts.isToday()) || ts.evenNumberIsValid()) {
    System.println("Deleting Background Service: " + ts.evenNumberIsValid());
    Background.deleteTemporalEvent();
    } else {

    System.println("Setting up Background Service");

    Background.registerForTemporalEvent(new Time.Duration(ts.getDuration(dailyTargetTime)));
    }
    } else {
    Sys.println("****background not available on this device****");
    }
    }


    I can see popping up the right message on the console if I end the widget causing the simulator watch to show a big triangle. After firing a temporal event from the simulator nothing happened although I called requestUpdate():

    function onBackgroundData() {
    System.println("I am alive");
    Ui.requestUpdate();
    }


    Now I am wondering how to test that beast....Or did I something wrong?
  • getServiceDelegate() is called when the temporal event "fires" to run the background, so if you don't have a temporal event running, it won't be called.

    I'm not sure why you are registering the temporal event in onStop, unless you only want it to run when the widget isn't running, but in that case, you'd want to delete it in onStart.

    OnStart() and onStop are also a bit tricky, in that they run when the widget itself starts/stops, but also when the background starts/stops. One Trick is I've used is a variable such as "isBackground", initialed to false; Then in the background, set it to true. As this variable isn't shared between the main widget and the background, in onExit(), if isBackground is true, that's onExit for the background, if false, the main app is exiting.

    I don't think you need the (:background) for the base app, but you get a warning if you don't have it, but it still works.

    When is is you want the background to run, and when don't you want it to run? If the widget isn't running, the last Background.exit() data will be availbe the next time the widget runs. (by way of onBackgroundData() )
  • Hi Jim,

    I don't want to pass any data to the widget in the background but just start the main application, i. e. the widget. My widget is a time tracker and user can store timestamps. If the last tracked timestamp was today and there is an uneven number of timestamps in the today's timestamp array I want to start the service. Before a certain duration expires I want to start the widget again to alarm the user.

    I thought it's best to double check this on unloading the widget but I could also do this if user stores a timestamp. But this isn't done in the base class.
  • Have you looked into Background.requestApplicationWake() ?
  • No, I haven't yet looked into that. But this sounds good for my application.
  • Hi Jim,

    I tried this but I am still wondering how to test this. As I said, I end the widget by clicking on down button in simulator's watch which shows me a big triangle. After that I fire a temporal event from the simulator but nothing happens.
  • Have you just tried waiting for the event to fire on it's own? You wont see anything unless the background uses Background.requestApplicationWake(). Otherwide the data for the main app is just queued up for the next time the app runs.
  • I tried waiting, but nothing happened. Therefore I moved the service request from onStop to another class of my application, tried to setup a temporal event by firing an event on duration 300 sec (as you did in your example), but the widget isn't started at all on my physical watch. Is there something I could do wrong? It looks so easy, but in praxis it is not very easy
  • When running in the sim, have you tried adding a whole bunch of Sys.println calls? I mean like some specific calls, like when you start or stop the temporal event, initialize in the background, etc? Leave the widget running in the sim and check things are happening when you think? As I said earlier, doing things in onStart/onStop can be tricky with backgrounding. Just a wild guess, but you may not be registering the temporal event or if you are, then deleting it when you don't expect.
  • For some reasons I can’t find source code of your example. Could you help me with it? Thank you!