A few questions on Fenix 3 development

Former Member
Former Member
Hello

I've tried connect iq dev this week-end, and first I must say the first experience is positive, it is more easy than I thought to develop a watch face.

After a few days of experience, here are a few feedback / questions I hope you'll consider

1/ Access to last known location on watchface.
I'm trying to add a few astronomical features to a face, and this would really help. I understand the battery conservation issues, but it would be very useful to have an API to get the last location (user beeing responsible to update it once in a while) - not to start GPS & query location like the current sensor API does for widgets.

Can it be submitted as a change request please?

2/ more information on watch face lifecycle - what are the exact conditions that trigger onExitSleep / onEnterSleep?
what is the consequence for the app? is on update called more frequently?
Maybe this is in the doc, but I couldn't find it.

3/ difference between simulator & device
I understand onUpdate() should be called every minute, it's called a lot more in the simulator - is this on purpose?

also on the device, I have the impression on update is called more than 1 a minute.

4/ partial screen update
I'm considering a few time consuming data on the watchface, it would be very helpful to save power (& improve usability) to allow the watchface to redraw just a label / part of screen (to update the time for instance) and redraw the full screen just once in a while (eg every hour). this would help us developper perform the power management.

Hope you'll consider it as well.

Thanks for a nice product & answers,

Best regards

H.
  • the Garmin folks can tell you more, but here goes:

    1) the watchfaces are very limited in what they have access to - no sensors, comm, button pushes, etc - to save on battery. And as a general note, not all devices have things like a baro sensor or compass and to get a heading with GPS, GPS has to be running, and the user has to be moving to get a heading.

    2) Watchfaces run in what's called "low power" mode most of the time, where the watch only updates every minute. When a user moves their oarm in the proper way, it leaves low power, and updates every second, and drops back to low power mode after about 10 seconds. onExitSleep() is when the watchface leaves low power mode, and onEnterSleep() is when it goes back into low power mode. In these routines, you can set a boolean so that you can do things like only display seconds if not in lower power mode (displaying seconds when it's only updating every minute doesn't make sense). Again, it's to save battery. On the top menu of the simulator is "low power", where you can switch between 1 sec and 1 minute updates.

    3) many differences - too many to name! You'll learn them for your device when you start using your stuff on the real device (and they are different between devices.) And note, the devices are very different too when it comes to colors and fonts!

    4) this one is a bit tricky, and I'll leave it for others that have better ideas on how to do this than I do. With 2), understand that onUpdate() only gets called once per minute at most times, and that's where the watchface does it's thing.... In the simulator, "enter low Power" to see how it works there.

    Depending on what you're trying to do, maybe it should be an app and not a watchface, as apps have more functionality available to them.

    In an app for example, you can fire up position using "LOCATION_ONE_SHOT" on a timer every few minutes and get the current GPS location. I do that in a weather app I wrote, (every 20 minutes), and then use that to get the data from the weather station closest to my location.
  • Former Member
    Former Member over 10 years ago
    thanks for the answer

    it's clearer about low power & the simulator, and the boolean should do it for what I have in mind - I'll give it a try.

    About the last location I realize the point about power, I'm thinking a simple query to a stored data without turning on GPS, like when we request the date.
    It would be great to do stuff like the sunset time that can be displayed on the default watch, for instance.
    (&User can still turn on GPS once in a while manually, if they want to update location for the face)

    I see another question requesting partial screen update on the forum, so not sure it's in the API yet (although I'll keep exploring / playing with it).
  • With updating part of the screen, you probably don't want to use layouts, but use the dc with things like dc.drawText(). Within onUpdate(), control when you do a dc.clear(), and which part gets updated (for example, update the time on every call to onUpdate(), but other data, only 10th time it's called).
  • Former Member
    Former Member over 10 years ago
    1. We definitely already have a feature request logged for last known position in watch faces. We'd probably already have it added in if we didn't have conflicts with our permission system we need to work around first.

    2. I think Jim explained this pretty well.

    3. There are things you are bound to run into, but we are trying to eliminate them. The main difference you noticed is just the triggering between enter/exit sleep.

    4. You can certainly update only part of the screen. The real gotcha there is just that when your watch face is started, stopped, or if something on the system pops over it, there may be a period where the view is animating, and partial updates would be insufficient. I'd like to see a graphic flag that can let you know when the display buffer has been modified by the system so partial updates like this are possible, but we don't have a design for that yet.
  • Brian, on #4, wouldn't "onShow()" be called if the screen was overlaid and becomes visible again? It would be called for the first time it's shown too, I assume I've not tried it, but that might be a way to indicate a full draw was needed to a watchface or app. (with "onHide()" indicating it's about to be overlaid or removed)

    (I've always assumed that this is what onShow() and onHide() was used for, but never found a reason to use it)
  • Former Member
    Former Member over 10 years ago
    Yes, those events should trigger when the display animates in and out. I am not certain of the exact timing without doing some direct testing. I think with a bit of experimentation, you could come up with methods to detect the times the display needs to be fully painted, but I think it would be nicer if we made it simpler in the API. Doing so could allow noticeable power improvements for watch faces that have heavy graphical items that don't always have to be updated.
  • Former Member
    Former Member over 10 years ago
    Re partial updates. From what I've seen the behavior is as jim suspects, onShow will be called with any push, pop, or switch. IMO The hardest part of partial updates is choosing what part of the screen to refresh. Is it worth the extra power of calculating what parts of the screen have changed, drawing in a blanking shape to clear the old pixels, then drawing in just those items that need it. Since we're talking about a watch face, consider the process...

    - Split the time into individual numbers
    - Go through each item and see if it needs updating.
    - Are we using fixed width font? If not have to calculate spacing.
    - Draw in blanking shapes to clear set pixels, which must be a shape to cover the existing number.
    - Draw in new numbers

    That's a really rough list, with items missing. I haven't tested to see which is the most efficient, and with that list I don't care to.
  • Former Member
    Former Member over 10 years ago
    I wouldn't bother with partially updating time. If you have a fixed width font it probably isn't too difficult, but I doubt you are going to see power improvements from not drawing the hours digits each minute. The things that might be significant enough to make a difference are things like the graph on ActiFace. I suspect that takes quite a few graphics operations to output, and only doing it every 10-15 minutes could make a difference over drawing every minute.
  • Former Member
    Former Member over 10 years ago
    thanks for all the answers. I've managed the partial redraws.
    Hopefully in a couple of day the project should be ready :)
  • Former Member
    Former Member over 10 years ago
    Hello,

    I took some time but managed to implement the partial redraws. It was complex because I ran into a weird behavior:

    The full layout of the face takes > 1 sec - so without any partial redraws, the watch would basically run forever on update (triggered every second), also causing the button to be very unresponsive.

    But with partial updates, I ran into a very weird issue at first - the screen would not display properly when initially showing the app.
    I eventually narrowed the issue down to vertical animations (for instance when transitioning from the preferences menu or from widgets). With horizontal animations however (like when transitioning from apps), it was displaying fine.

    I have no clue why this is so, and it might be a bug - but if the face is too long to update, some animations won't work (the drawing you perform seems to "land" on a context that is no longer displayed...).

    To fix it, I delayed the full update. And it needs to be delayed at least 3 seconds for it to work for all the animations. So 1st I do only the fast & partial update and the full layout appears only after 5 secs or so (3 sec+ of delay + the actual time to draw it).

    If anyone has some ideas, I'll be interested to hear it. This is the last glitch I'm trying to fix before submitting.

    IF anyone is curious, it's a watch face the display in real time the sky for the user.