Data Field variables lost when you Resume Later

Apologies if this is already covered - I wasn't successful searching for this topic. It appears that any global variables declared in the Ui.DataField or Ui.SimpleDataField classes go out of scope when you stop the activity timer and choose to "Resume Later". When you do resume the activity, all variables are reinitialized. Am I missing something? Is there a way to persist values through a Stop - Resume Later - Start cycle?
  • You should be able to save your data App.onStop(state) and read them back in App.onStart(state).

    using Toybox.Application as App;
    using Toybox.WatchUi as Ui;

    enum {
    PAUSE_COUNT_PROPERTY = 1
    }

    class MyDataField extends Ui.SimpleDataField
    {
    hidden var _pauseCount;

    function initialize() {
    SimpleDataField.initialize();
    _pauseCount = 0;
    }

    function compute(info) {
    return _pauseCount;
    }

    function onStart(app, state) {
    _pauseCount = app.getProperty(PAUSE_COUNT_PROPERTY);
    if (_pauseCount == null) {
    _pauseCount = 0;
    }
    }

    function onStop(app, state) {
    app.setProperty(PAUSE_COUNT_PROPERTY, _pauseCount);
    }

    function onTimerPause() {
    _pauseCount += 1;
    }

    function onTimerReset() {
    _pauseCount = 0;
    }
    }

    class MyApp extends App.AppBase
    {
    hidden var _dataField;

    function initialize() {
    AppBase.initialize();
    _dataField = new MyDataField();
    }

    function onStart(state) {
    _dataField.onStart(self, state);
    }

    function onStop(state) {
    _dataField.onStop(self, state);
    }

    function getInitialView() {
    return [ _dataField ];
    }
    }
  • You should be able to save your data App.onStop(state) and read them back in App.onStart(state).


    Thanks to you, now I can! :-)
  • You should be able to save your data App.onStop(state) and read them back in App.onStart(state).

    function onTimerPause() {
    _pauseCount += 1;
    }

    function onTimerReset() {
    _pauseCount = 0;
    }

    }


    I've got a follow up question on this thread... I'm able to save and retrieve values in the object store to preserve context when an activity is stopped so that you can "Resume Later". However, once I've saved values, they seem to persist even after the activity has subsequently been resumed and then terminated (eg. "Save", "Discard"). Furthermore, the two timer-related events in your code sample (shown above in red) don't seem to be functional (I'm using an Epix), so the Pause Count in the sample code never increments beyond zero. Stated another way, the object store doesn't seem to reset implicitly when I stop an activity (or start a new one), and I haven't figured out how to tell the difference between an "onStop" that occurs in a "Resume Later" situation vs. one that indicates the activity has ended. Am I missing something obvious? (Perhaps a more current API that's not available for my device...? :-( )
  • Former Member
    Former Member over 8 years ago
    You can determine when a new activity starts by looking at average speed. If it is zero, you have a new activity.
  • You can determine when a new activity starts by looking at average speed. If it is zero, you have a new activity.


    Hmm... I've encapsulated all needed object store code into a persistent "storageHandler" which I'm calling from the onStart and onStop events, passing the app object to the storageHandler so it can access the application's object store methods. The storageHandler has three modes: 1) Save persistent variables (to the object store), 2) Load persistent variables (from the object store), or 3) Reset persistent variables (to initial values).

    From what I can tell, the onStart event occurs both when a new activity starts, as well as when a "Resume Later" activity is resumed. If I can distinguish between these two cases within the context of the onStart event then I can call the storageHandler and request a Reset or Load as appropriate. However, in the context of the onStart event I don't believe I have access to the activity's info properties - or do I?
  • Former Member
    Former Member over 8 years ago
    However, in the context of the onStart event I don't believe I have access to the activity's info properties - or do I?


    Correct. Check average speed in your compute function and clear them when average speed is zero or null.
  • Correct. Check average speed in your compute function and clear them when average speed is zero or null.


    (I'm mobile so forgive any mis-remembered property names... :-)

    As an alternative, could I compare info.timerTime with info.elapsedTime, assuming that the former will be < the latter when an ongoing activity is being resumed? Average speed may not be as well-suited for some of my data fields which are targeted for indoor activities that don't necessarily include movement that would reliably result in any speed > zero.

    Am I also correct in thinking that the general approach to loading, saving and resetting persistent variables that we're discussing would - by implication - always leave the application's object store filled with "non zero" values, regardless of whether the activity was most recently suspended (i.e. "Resume Later"), saved or discarded? (Stated another way - there's no way we can detect the difference between an onStop event that results from any of those three ways that an activity may stop executing.) Not that this would be a problem - just trying to understand as much as I can about how this stuff works.

    Thanks for sharing the benefit of your experience. :-)
  • However, once I've saved values, they seem to persist even after the activity has subsequently been resumed and then terminated (eg. "Save", "Discard").

    It isn't supposed to. If you want it to forget the persisted values, you need to delete them, or write your code in such a way that they are properly reused.

    Furthermore, the two timer-related events in your code sample (shown above in red) don't seem to be functional (I'm using an Epix)

    It sounds like the epix firmware, or possibly the just version you are using, doesn't support the new timer methods. My reading of ${SDKROOT}/bin/devices.xml confirms that the epix supports 1.2.1 only, and these functions were added in the 1.3.0 SDK.

    My code was just an example that assumed support for the 1.3.0 SDK features. When a lap button press occurs, onTimerLap() should get called and the count is incremented, and when the activity is saved or discarded, onTimerReset() should be called and the count is reset. When unloading the data field, the current count would be saved, and when loading it up it would be restored. If the callbacks are invoked, you should never need to do anything to reset the stored value as it would always be correct except when the watch crashes. If you really wanted to handle that, you'd save the value every time it changed, not just on exit.

    Stated another way, the object store doesn't seem to reset implicitly when I stop an activity (or start a new one), and I haven't figured out how to tell the difference between an "onStop" that occurs in a "Resume Later" situation vs. one that indicates the activity has ended. Am I missing something obvious?

    This is why you want the callbacks. You can use a few of the bits of data from the data field to tell if the activity has reset (the start time was not null and is now null, or something like that), but the safest and simplest way is to only support devices with the 1.3.0 SDK support and use the callbacks.
  • Correct. Check average speed in your compute function and clear them when average speed is zero or null.

    Is there some reason that you can't you call Activity.getInfo()? Also, average speed can be zero if GPS is off, so this isn't a reliable way to detect an activity reset.
  • Is there some reason that you can't you call Activity.getInfo()? Also, average speed can be zero if GPS is off, so this isn't a reliable way to detect an activity reset.


    Not in a position to try any code this attention, and only a few weeks into ConnectIQ so I'm still wet behind the ears - but if I can access Activity.info properties in the context of the onStart event then that's quite helpful. As for activity properties that could be used to distinguish a new activity start (from scratch) from an existing activity continuation (following "Resume Later") - would it be valid to test for timerTime < elapsedTime as an indicator of a continued activity?