ConfirmationDelegate on exit and "state machine" work on simulator, not on watch.

I'm trying to learn monkey c by doing the simplest of app. A small referee app, where you can specify number of periods and period length. For a game I have simple state machine of the game WaitingForStart -> Running/Pause -> Break -> Running/Paused (etc if several periods) -> Ended

Each period/break/pause has a timer countdown, a total countup and a pause/break countup, ruled by one Toybox.Timer. The state determines which counter(s) that should increase/decrease.

I have two problems:

1) I use onSelect to transition between the states. The Toybox.Timer.start() when I move from WaitingForStart -> Running. Timer.stop() when I enter Ended. This works in simulation on Visual Studio Code, but not on my watch.

2) To avoid closing the app by accident, I have a confirmationDelegate in my onBack(). This confirmation works on simulator, but not on the watch. On the watch, the app closes on my first press on Back.

What could be the issues here? Where should I start digging?

  • Forgot to mention the real problem with 1). On the simulator, I can transistion from Ended -> WaitingForStart, so I can do back-to-back games without closing the app. On the watch, I cant get from the Ended state.

  • Sounds like yo0u are doing a device-app and not a data field.  Which device?

    In your onSelect, are you returning true in all case?  You should.

    in onBack, return false if you want the app to exit and true if you don't.

    In the delegate for the confirmation, you might be able to just do

    System.exit()

    if the user wants to exit.  If you are recording an activity, there is more involved in exiting.

    You may want to post your code if this doesn't work.

  • Yes, it is a device app. My device is a Fenix 5X Plus (want it to work on FR230 as well, that's why I'm using App.getApp().getProperty() etc). No recording is necessary, so I can just exit.

    function onSelect() as Boolean {
    var state = App.getApp().getProperty("game_state");
    pauseNotify();
    switch(state) {
    case GameState.WaitForStart:
    // Init all parameters for game start.
    App.getApp().setProperty("game_state", GameState.Running);
    _periodDuration = App.getApp().getProperty("period_duration");
    _currentDuration = _periodDuration;
    _numPeriods = App.getApp().getProperty("num_periods");
    _view.updatePeriodValue();
    startGame();
    break;
    case GameState.Running:
    App.getApp().setProperty("game_state", GameState.Paused);
    break;
    case GameState.Paused:
    App.getApp().setProperty("game_state", GameState.Running);
    break;
    case GameState.Break:
    App.getApp().setProperty("game_state", GameState.Running);
    break;
    // case GameState.Ended:
    // App.getApp().setProperty("game_state", GameState.WaitForStart);
    // initValues();
    // _view.updatePeriodValue();
    // _view.setGameStateValue();
    // _view.updateScores(_homeScore, _awayScore);
    // break;
    }
    return true;
    }
    And my onBack
    function onBack() as Boolean {
    WatchUi.pushView( new WatchUi.Confirmation("Exit?"), new ConfirmExitDelegate(), WatchUi.SLIDE_RIGHT );
    return true; // handled ESC input
    }
    class ConfirmExitDelegate extends WatchUi.ConfirmationDelegate {

    function initialize() {
    ConfirmationDelegate.initialize();
    }

    function onResponse(response) {
    if (response == WatchUi.CONFIRM_YES) {
    System.exit();
    // WatchUi.popView(WatchUi.SLIDE_IMMEDIATE);
    }
    return true;
    // else {
    // return false;
    // }
    }
    }
    The commented code in my ConfirmExitDelegate was my first attempt, which worked on the simulator but not the device.
    As you see, I always return true in onSelect. I tried your suggestion with System.exit(). That works. But another thing puzzles me: I temporarily disabled the transition from GameState.Ended to WaitForStart, as you can see by the commented code in the case statement.
    As expected, I can't start a new game by pressing onSelect() in my simulator. But on the device, I transfer from state.Ended to state.WaitForStart... I can't understand why it behaves so unexpectedly! I removed the app, restarted the device and then installed the app. Still, I transfer from Ended to WaitForStart as if the commented code is alive. Why?
  • Try debugging on the device itself, using println() calls

    See this section of the New Developer FAQ to see how/where to crate a log file to get the results

    https://forums.garmin.com/developer/connect-iq/w/wiki/4/new-developer-faq#debugging

  • Thank you for your suggestions! I will have a look into that. Seems as the app behaves differently on my 5xplus compared to my wifes 7s (hers acting as it should with the state machine but with other quirks. Slight smile

  • This is not strictly related to original question, but I have a feeling you know this answer.
    Since I want to change some settings via the menu, is it best to work with global variables or always get/set values via Application.getApp().set/get()? To keep track of countdown values etc when switching between views? Which is more effective?