Widgets for Fenix 6

Thanks Garmin for the SDK update, 3.1.3 allows to get watchface and data fields easily for the new watches, but doing the same job for widgets means some work...

Recompiling an "old" (fr935/fenix5) widget for the fenix6 shows only a small icon and the name of the widget which can be scrolled up and down using the keys but that's it. Does anyone have a small example source code for the new widget type?

  • Here's a work in progress for me, and the code is a bit more complex as it's a widget with a background process to get weather data.  On some devices (the pro devices), it will update if onBackgroundData is run (it's in the doc - about Ui.requestData()).  So it doesn't just need to be simple text.

  • I believe adding the (:glance) annotation just make is easier for the compiler to exclude those functions and classes from devices that don't support glance views.  If you leave it out, everything will still work, but the compiler will give you a warning that it supports glance view but contains no annotations.

    When running in glance mode, the app has less memory available to it. The (:glance) annotation lets you specify which code needs to be available to glance mode. If your application is small, you can probably get away without the annotation at all, but at some point you'll start running low on memory.

    One further thing to watch out for, besides the memory, is that the glance view doesn't support everything the main widget view does - Positioning isn't available, where Sensor is. Not sure what else, and it would be handy to have the differences documented. Below is the Glance from the widget I mentioned - the main view gets your location and does some web calls to evaluate the elevation and atmospheric pressure where you are, the glance view reads those from sensor info, so will give you a live value albeit dependent on your current sea level calibration.

  • Something else to note here, is when in glance mode, Ui.requestUpdate() doesn't work the same on f6 pro devices vs non-pro (lower memory devices), so even if you could fire up GPS, on non pro devices, the glance itself wouldn't be updated as you expect.

    from the PG:

    "Devices that have less memory [11] will start the app only when the system deems it appropriate, and calls to WatchUi.requestUpdate() will have no effect. Such a device could update the ‘Glance Page’ when it becomes visible (activated) and at least 30 seconds since last update."

    How I see this, is you really want to have the data available when the widget starts in glance mode - either something at hand, or something that can be pulled from Storage.  You don't want to do a makeWebRequest() and show data when that completes, for example.

    In the weather widget I mentioned, I do the makeWebReqest in a background process and save the result in Storage, so I just get the data that way.

  • The (:glance) annotation lets you specify which code needs to be available to glance mode. If your application is small, you can probably get away without the annotation at all, but at some point you'll start running low on memory.

    Travis, you may have just hit what I am seeing on my bug report where I am seeing out of memory errors on the F6 and Marq devices.  Since I have not released a version of the widget "optimized" for glance view, I bet it is trying to run all of the webrequests while still in widget mode.  Memory usage being around 30k already it could actually run out depending on how big the dictionary is to check the phone status.  Perhaps once I add the glance annotations, it may solve my issue.

  • Thanks, meantime it's getting a little bit better (dealing with a 'initRessource missing' message, but that's another story)...

    Using my simple Screeeny-Tool also for the fenix 6 series now to create a program within few seconds :)

  • Hey Jim, I'm making my background request the same way and it's working fine. Thanks for the tips!

    Are you able to change the icon for the glance during a background request or are we stuck with showing the default widget icon (in your case the weather underground icon) for the duration of the glance view?

  • Yeah, that's what I've missed  Upside down

    I thought that the 'Enter/Select' button in the simulator would change from the glance mode to standard widget mode - however I've added the shortcut Ctrl+Shift+G to the Screeny tool (see below) so the state can easily toggled now Slight smile


    Compiling widgets still does not work perfect as the annotations (:glance) have to be commented, otherwise I get an error. The only explanation I have for this behaviour is that the compiler is not able to deal with annotations and removing unused sections will be done as a seperate process.

  • That's the launcher_icon for the widget.  I don't think you can change it in glance.

    Few may not notice but on many devices when you move to a CIQ widget, the launcher_icon and app name are displayed for a very brief time.

    I've not tried it, but I think you can display a small bmp within the dc of the glance view.

  • A nice simple template, thanks Jim.

    I notice you've worked around an issue I came across. In a standard view you can load a layout from a resources file, eg in onLayout(). According to the programmer's guide you should be able to do this from a glance view as well - so long as the resource is properly scoped. But it doesn't yet work. If the resource isn't scoped you correctly get an (out of bounds) error when the glance process tries to access the resource but if your do set scope="glance" on the resource you get a compiler warning such as "BUILD: WARNING: Layout resource 'GlanceLayout' specifies a resource scope, but resource scopes are not supported by device 'fenix6'." and again it fails at run-time. So, as you've done, you have to use direct drawing in onUpdate().
    Simon

  • In fact, as far as I can tell, there is some access to GPS allowed from a glance view.

    For example when I tried using Position.enableLocationEvents() I got, "Error: Permission Required Details: Permission for module 'Toybox.Position' required" but using Position.getInfo() seems OK.

    Unfortunately, of course, it's not much use since you don't know when onUpdate() will be called.