I just want to sync something to my Garmin watch!
Garmin connectivity for React Native Part 1 of ?
Garmin watches have apps! Sort of.
A quick look on the ConnectIQ Store and you'll find that these apps are pretty basic. If they have any connectivity beyond the watch, it's like something weird where you go to a website and enter a code on the watch, and then of course you find it's some kind of free trial for something that you're not even really sure if it'll work.
Syncing the watch with a companion phone app would be really clean, even if ultimately there's internet connectivity involved. IMO there's a lot of use cases for data on the watch that really don't warrant the complexity of a server. Here's an example: I was out of town, staying at an AirBnb. I went for a run with my Forerunner 955, which has built-in maps and lets me save the location where I'm staying, so I should be able to get back without my phone, even if I get lost. But what if I forget the 4-digit code locking the door? I'd like a little app to sync that info to my watch, that's all.
Garmin has an SDK for doing this, but it doesn't seem very popular, and it's hard to grep the documentation. There's an example repo, but, uh, this doesn't look very popular:
The only open PR suggests that the sample doesn't even work. Not good!
Further, there are commits to upgrade various things after that PR. Where do you start?
The first order of business is to get something working, at all. I'm gonna trust the PR, even if it's a little old.
There are three steps to prove this thing works:
Build the Android version
Build the watch app
See if they talk to each other
You can simulate bluetooth connections with emulators for both watch and phone with ADB, but that sounds like a pain, so I did everything on devices. I had to add my watch model to the watch app manifest.xml file, but I was able to build it prettty easily because I already had the CIQ Monkey-C Visual Studio Code plugin installed from a previous Garmin development misadventure (these install instructions are accurate):
There was a syntax error in the example somehow. I just had to add a missing return true
to a function and then the build made a .prg file that I needed to drag to my watch's app folder.
BTW, opening Garmin watch storage is a pain in the butt on a Mac. You need the "Android File Transfer" app. You'll want to plug in the watch first and then open the app, but, even still, most of the time you'll get an error that the watch isn't connected. Eventually, what worked for me was to:
Open the "Garmin Express" desktop app
Fiddle with the watch/ USB cable until the app recognized the watch
Close Garmin Express
Open Android File Transfer
In the meantime, the Android app built from the open PR flawlessly to my Pixel 4a, and was already reporting that it had connected to my Forerunner, but couldn't find the app on the watch. I restarted it after adding the watch app, and, voila!
Two-way communication was working! You can hold the middle-right button on the watch to access a menu that lets you send messages back to the phone, which appear as alerts. I was actually a little surprised it picked up the watch so fast; I figured I'd have to choose it from a list, wait a while, etc.
Next steps
Ultimately, I want to turn this into a React Native package via the Expo Modules API so I can interface with it in a React Native app. That will involve turning these demo calls into some kind of data in/ data out API. There's a whole separate iOS API, too, so this could eventually be cross-platform. Creating a module that just works with Android at the start feels like a plenty-big task, though.
But first, I want to upgrade everything in this demo project. The latest Expo SDK targets Android API level 33, so I'd like to get to that. I also want to layer in the more recent changes to the examples that weren't picked up by the original PR, especially since they change where Gradle looks for the ConnectIQ Maven package (as well as upgrading it to a later version).
These baby steps have me encouraged that this might actually work, though!