Complete
over 4 years ago

ACROPOLIS-2652

Background event system does not work

It seems the backgrounding system is broken at least on several systems (in my case Fenix 6). It is very easy to reproduce, please follow the steps I am describing below.

What I am trying to achieve: I want to create a widget that gets activated every 10 minutes, collect data via a sensor listener, and gets back to sleep until the next temporal event is triggered.

What I do:

  • I am registering my temporal event in method getInitialView() to start as soon as possible

            // ...
            Background.registerForTemporalEvent(Time.now());


  • I am registering my sensor listener in my service delegate method onTemporalEvent() when it gets called

  • if a temporal event gets triggered, i am restarting my temporal event at the time Background.getLastTemporalEventTime() + 5 minutes in method onStop()
     
          Note: I am aware that I can use recurring events that get triggered periodically. I used them, but they have the same effect. Why I am using the restarting option here is so i can clearly document what happens

            if (LastTemporalEvent != null) {
                    var NextEvent            = LastTemporalEvent.add(FIVE_MINUTES);
                    Background.deleteTemporalEvent();
                Background.registerForTemporalEvent(NextEvent);
            }
            else    {
                   Background.registerForTemporalEvent(Time.now());
            }


My problems:

  • it seems the background process is not triggered as it is supposed to. Sometimes it does, maybe an hour after it i should have been. But it seems not reproducable when it will.
       
  • IF (!) the background process gets started, using the sensor listener in my delegate doesn't give me 30 seconds as it is supposed to do, but only 1 or 2 (if at all). Yes, I am aware that the 30 seconds period can be cancelled at any time by the system, but the way that it always gets cancelled almost immediately renders sensor listeners useless in background processes.
    It can be argued that instead of a listener you can use the SensorHistory, but SensorHistory is not complete when it comes to some data, HRV for example.


One thing that seems very important here is that everything runs perfectly in the Simulator, so that's at least an indicator that my coding isn't completely wrong, I think.


Here is what happens when I generate text output on my watch (some remarks in [ ]):

onStop at 10:37:37
Temporal event NOW registered at 10:37:37
Next background event at 10:37:39
View initialized
Sensor listener registered at 10:37:39
Getting sensor data...1 seconds
onStop at 10:37:43
Next background event at 10:42:39
onStop at 10:37:44
Next background event at 10:42:39
[up to this point, I started the widget to initialize the background timer. Next event should be called at 10:42:39...]
Sensor listener registered at 11:44:37
onStop at 11:45:18
Next background event at 11:49:37
[...but it wasn't. In fact the background process was sleeping for over 1 hour, then registered the sensor listener but never executed the listener once. Then the next background event was scheduled but never executed...]



Because this issue can affect every app that uses the backgrounding system, this is in my opinion a high priority issue that should be solved as quick as possible!

If you need more info, please let me know. Thanks!

  • That's interesting, so it really seems to be clearly related to Fenix 6. So the only solution at the moment is to exclude Fenix 6 from the supported devices list in the manifest and hope that there are no other devices that have the same bug. I wouldn't be too happy if this is the only solution...

  • As an update, returned my Fenix 6 to the store because of this bug. Got a Fenix 6 Pro instead. Running same code now, and everything works. Background process updates as expected!

  • @GarminSupport Did somebody had a chance to look into this and verify if there is a problem? With the source code provided run on a Fenix 6 this should be verifiable very fast. As long as i don't know how to handle this the development of my current app is on hold unfortunately...

  • I have the exact same problem with Fenix 6. I have just a simple background process that retrieves weather data. All my previous watchfaces works with no problem on Fenix5 and with simulator. With Fenix6 it will not trigger the background process, unless I switch to widgets once or when a message/notification is received (like once going to widgets). Fenix5 instead works always with six of my watchfaces with automatic background update, so I don’t think it is in the code. Fenix6 just don’t trigger the background event when timeout is reached.

  • Hi Travis, thanks for your feedback.

    I did as you suggested and removed all apps from my watch. I went over my widget list and did the same (keeping only default ones).

    I then programmed a small widget that only does the "basic" things I want to test, registering a background process with a temporal event and a service delegate with my sensor listener logic. But unfortunalety, not a single time my background process was triggered in a 1 hour running time, so there should have been many occasions for the background process to be triggered. Again, in the simulator everything runs as intended.

    I am using a Fenix 6 so I would expect memory should not be a problem, especially because I am not running any other app or widget on my watch.

    Here is my very quick-and-dirty coding to reproduce it. If you or somebody from the support team could reproduce it maybe on a Fenix 6 to see if this occurs device specific?

    using Toybox.WatchUi;
    using Toybox.Application;
    using Toybox.System;
    using Toybox.Time;
    using Toybox.Sensor;
    
    (:background)
    class BackgroundTestApp extends Application.AppBase {
    
        function initialize() {
            AppBase.initialize();
        }
    
        // Return the initial view of your application here
        function getInitialView() {
    		
    		Background.registerForTemporalEvent(new Time.Duration(5 * 60));
    		
    		System.println("[getInitialView]: Background process registered");
    
            return [ new BackgroundTestView() ];
        }
    
    // **************************************************************************************************************
        function getServiceDelegate(){
    		return [new MyServiceDelegate()];
        }
        
    }
    
    (:background)
    class MyServiceDelegate extends System.ServiceDelegate {
    
    	function initialize() {
    		System.ServiceDelegate.initialize();
    	}
    	
        function onTemporalEvent() {
    
    		var options = { 
    	    		:period=>4,               	// 4 second sample time
    	    		:accelerometer=>{
    	        		:enabled=>true,       	// enable the accelerometer
                        :sampleRate => 25,
                    }
    			};    	
    
    		System.println("[onTemporalEvent]: Background event triggered");
    		
    		Sensor.registerSensorDataListener(method(:sensorCallback), options);
    		System.println("   Sensor listener registered");
        }
        
    	function sensorCallback(SensorData)	{
    		System.println("Sensor data incoming...");
    	}
    }

    Thanks!