HTTP request over device Wi-Fi specification

I was reading in the documentation, regarding the http Communications moudule, that:

"Monkey C exposes a high level APIs to allow calls to basic web services through Garmin Connect Mobile"

Soruce: https://developer.garmin.com/connect-iq/core-topics/https/

  1. Does that mean that i can only make http request trough the Garmin Connect app ?

  2. By trying to make a http request with the Communications modules on a simulated device i've notice that i'm able to make a succesfull request even when i'm not connected to a phone device. Does that mean that i can also make a htt request over the Garmin device Wi-fi without passing trough the Garmin Connect app ?

  3. Is there any way to check programmatically if the Garmin devies have a built in network support ?
  • I’ve started implementing this, and the first thing I noticed is that checkWifiConnection() reports its result asynchronously for all three simulator states (Not Initialized, Not Connected, Connected). This is expected since it uses a callback, but it wasn’t a given, because there is at least one other API, makeWebRequest(), that can invoke the callback synchronously during the function call itself.

    So since I want the app to start up in a different view depending on the result, I need to return an intermediate “Checking WiFi…” view from getInitialView() first.

  • Maybe you need to start with that view, and it should close itself or pop up the next view depending on the result of the check. It might do a flicker though, depending on the device speed.

  • Maybe you need to start with that view, and it should close itself or pop up the next view depending on the result of the check.

    I tried to do this, but interestingly the switchToView call I placed in onShow() or onUpdate() had no effect. At that point, WatchUi.getCurrentView()[0] is still null as well. I’m not sure whether this is a general limitation of those methods, or if it’s because the view is being prepared as the initial view.

    I’ll try setting a short timer instead and see if that works.

  • It’s interesting. It looks like you can enqueue events during getInitialView(), and they may get processed before the initial view is fully shown.

    When I start a timer from getInitialView() with a 50 ms delay, the callback fires while WatchUi.getCurrentView()[0] is still null, and WatchUi.switchToView() has no effect. With a 500 ms delay, getCurrentView() returns a view and switching works as expected.

    What also works reliably is starting the timer after the initial view’s first onUpdate(). In that case, even a 50 ms delay is enough, and the switch succeeds when the timer fires.

    So far this is all based on simulator testing. I still need to verify whether real devices behave the same way.

  • I also tried System.getDeviceSettings().connectionInfo. While it does include an entry for WiFi, it always reports it as disconnected, even when WiFi is set to connected in the simulator. At least that’s what I’m seeing during normal app operation. It might behave differently while the device is in sync mode.

  • maybe even better to put the timer to onLayout?

  • maybe even better to put the timer to onLayout?

    Not entirely sure, events might slip in between onLayout() and onUpdate(), though it’s likely they’re executed back-to-back.

    One more question: do main-app events still run in sync mode? For instance, could a timer event fire while waiting for a makeWebRequest() response in sync mode?

  • I have now implemented the first SyncDelegate. While it works, the overall API appears to be fairly fragile, at least in the simulator. If, after calling Communications.startSync2, I invoke other functions with relatively simple tasks, such as writing to System.println, the sync is executed but the UI is not displayed. I am not sure whether this is a simulator-specific issue or something that would also occur on a real device.

    Another observation: when calling WatchUi.popView() together with Communications.notifySyncComplete, the confirmation dialog is not shown, and the view from which the sync was started is popped. However, if WatchUi.switchToView() is used to return to the original view instead, that view remains on the stack, but the confirmation is still closed. I do not mind the confirmation and only stumbled upon this behavior by accident.

    Given these behaviors, I am wondering whether it might be possible to keep a Wi-Fi connection effectively active in the background while continuing to use the normal app UI. Has anyone tried this?

    One more question: do main-app events still run in sync mode? For instance, could a timer event fire while waiting for a makeWebRequest() response in sync mode?

    I now also have an answer to this question: yes, they do. I have a timer that regularly polls a REST API. This is unrelated to the REST API call I want to make in the SyncDelegate. If the timer happens to trigger while sync mode is active, it runs, and it also succeeds, i.e. it also benefits from the open WiFi connection.

    In my case, this leads to some issues, and I would actually like to disable that timer and only re-enable it after the sync mode has finished. This brings me to another shortcoming: I believe the sync mode is missing a callback that is invoked once the sync is complete and the Wi-Fi connection has been closed.

    For now, I will try to work around this by starting a timer event when calling notifySyncComplete.

    And one more thing: this may also be a simulator-specific issue, but in my case the message passed to startSync2 does not appear to be shown anywhere.

  • I’ve completed my implementation now.

    During testing I noticed a few quirks that might be worth keeping in mind:

    1. onStopSync behavior
      onStopSync is not only called when the user interrupts the sync, but also when the sync is stopped by calling Communications.notifySyncComplete() with an error message. I could not find this documented and I am not sure whether this is intentional.

    2. Wi-Fi availability after sync ends
      After a sync ends, the Wi-Fi connection remains available for a short period of time. My app uses a timer to poll a REST API. Initially I relied only on the timer result to determine whether a phone connection was available. However, when the poll ran shortly after sync completion, it sometimes succeeded even though no phone connection was available.

      I had to combine this with checking System.getDeviceSettings().connectionInfo to determine whether the poll actually succeeded via a phone connection.

    3. Communications.checkWifiConnection() blocks sync
      If a sync is started via Communications.startSync2() while a Wi-Fi connection check is in progress, the sync shows an error to the user saying that the sync is already in progress. This is not an exception, but a UI error.
      Originally my timer checked Wi-Fi every time a poll failed due to a missing phone connection. Since this happens in the background, the user can still trigger a sync, and many of those sync attempts failed because a Wi-Fi check was running. I adjusted the logic to only check Wi-Fi the first time a missing phone connection is detected and then assume it remains available. If the user loses Wi-Fi later, the sync fails gracefully.

    Other than that, everything worked as expected.

    I am still tempted to try entering sync mode directly on app startup, showing the progress view, and then effectively running with a permanent Wi-Fi connection. From a battery perspective this should be acceptable because the app is a widget and users typically spend no more than 15 to 20 seconds in it. That said, I am hesitant to build on undocumented behavior.