Acknowledged
CIQQA-3306

Calling ActivityRecording.createSession with invalid SPORT or SUB_SPORT causes exception

Calling ActivityRecording.createSession on an actual device with SPORT or SUB_SPORT that is invalid for the watch model causes an exception.  While this may be by design, there is no documentation with respect to the valid selections for a specific watch model.  The simulator accepts all values without throwing an exception.

For example this causes an exception on a Fenix 5 Plus:

                    session = ActivityRecording.createSession({          // set up recording session
                            :name=>"ABC",                              // set session name
                            :sport=>Activity.SPORT_MEDITATION,                // set sport type
                            :subSport=>Activity.SUB_SPORT_BREATHING          // set sub sport type
                    });
 
It would be preferable for invalid values to be coerced to SPORT_GENERIC , SUB_SPORT_GENERIC rather than throwing an exception.
  • > To ensure that this is the case, the flag "--disable-api-has-check-removal" should be passed to the compiler, or optimization should be disabled.

    Tbf, API has check removal is now disabled by default starting with 8.2.1, but I guess it wouldn't hurt to pass that flag anyway.

  • This makes sense [although it's not good behaviour], because clearly the fenix5plus device file [and sim] don't "know" that fenix5plus doesn't support SPORT_MEDITATION. If they did, then the code in OP would crash at runtime.

    So I think the ideal fix would be to fix the sim / device file so that using an invalid sport/subSport causes a fatal error at runtime, *and* that any compile-time removal of related has checks should resolve to the correct value [e.g. Activity has :SPORT_MEDITATION should resolve to false at compile-time, for fenix5plus]

    Again, the core problem here is that the fenix5plus device file / sim don't model the true limitations of fenix5plus, when it comes to Activity sport and subsport.

    [2/2]

  • > You can also try to check with the "has" operator if the constant exists

    btw, for this to work, I think API has check removal has to be disabled. To ensure that this is the case, the flag "--disable-api-has-check-removal" should be passed to the compiler, or optimization should be disabled.

    I just tried building a test app with Activity has :SPORT_MEDITATION on fenix5plus, and with "-O3pz" specified as a compiler option, the has check is resolved to true at compile-time, which ofc means that code such as the following would still crash at runtime, even with the has check. (I validated this by looking at the generated .mir file for the source file in question).

    [1/2]

  • I think the best fix that could be made on Garmin's end would be to update the sim / device files so that invalid values for sport and subSport cause a fatal error, just like they do with a real device.

  • > throwing an exception.

    > It would be better if the exception would be catchable.

    By definition, if it's not catchable, it's a fatal error, not an exception.

    Garmin's terminology:

    (https://developer.garmin.com/connect-iq/monkey-c/exceptions-and-errors/)

    - Fatal errors: not catchable, cause app to terminate immediately

    - Exceptions (non-fatal errors): catchable (failure to catch an exception is a fatal error though)

    Conflating these two kinds of errors leads to things like suggesting that "Uncaught Exception" is a kind of exception (no, it's the error you get when an exception is not caught), or missing the fact that InvalidValueException and the "Invalid Value" fatal error are actually 2 completely different things. It's not the right way to look at things, because even if we CIQ vets know what we're talking about, others who aren't super familiar with CIQ won't understand. For example, in reading the OP, if I didn't know better, I'd think that createSession is throwing a literal exception that can be caught, but in reality we all know it's a fatal error that can't be caught (which is very inconvenient for the app dev and user.)

    I agree that it would be better for this condition to be a literal exception, but Garmin probably isn't going to change this, especially on a device as old as Fenix 5 Plus.

    It would be preferable for invalid values to be coerced to SPORT_GENERIC , SUB_SPORT_GENERIC rather than throwing an exception.

    It seems to me that you could write this code yourself, with flocsy's suggestion of using the has operator to check if the desired enum values are available at run-time. Again, it's not likely that Garmin will change this for Fenix 5 Plus.

    > The simulator accepts all values without throwing an exception.

    Yeah, this kind of thing is def frustrating. Just another example where the simulator doesn't accurately model the limitations of older devices, and said limitations aren't fully documented.