1hz Watch Faces - Q&A

I'm not sure if many folks have been trying the new "always active" watch faces in 2.3.x, but the 2.3.0.beta1 has been out for a month or so now. It's probably getting close to the 2.3.1 SDK release, and thought I'd start a Q&A for the feature, and start with some of what I've picked up in adapting a number of watch faces to use 1hz.

I'll be calling this feature "1hz", as that's what it really is - being able to change the screen on a watch face every second.
The most common thing will likely being the ability to display seconds all the time. One thing I'll note right off, is while you can update the screen every second, the underlying data still changes at the rate it did before, so if you use 1hz for the HR, you won't see the HR change every second.

A few basics.

  • 1hz is only available on some watches. The f5, f5s, f5x, 935, and Q5, but if you support a bunch of different watches, you can easily have it on some and not others.
  • 1hz happens by way of a new onPartialUpdate() for watch faces. onUpdate() is just like it was in the past, and when you are allowed to do a 1hz update, onPartialUpdated() is called. You don't have to change a thing in your code if you don't want to use 1hz.
  • onPartialUpdate() is VERY strict as to how long it can run. You have a "power budget", and the rule is that each minute, the average run time each second can't be greater than 30 milliseconds. This is the tricky part! :)



I started with the Analog Sample in the SDK, which does show what to do, but has some things you don't need to do for digital watch faces - there's no second hand passing over a bunch of different places on the screen with a digital one. The time is in a fixed spot on the screen in most cases.



Anyway's, the first thing I did was cut back to the basics of what was needed for a digital WF. I'll attached a project with a very basic 1hz watch face, but first a few notes about it.

  • vs1hzapp.mc shows how to use the delegate for the power exceeded deligate on watches that have 1hz, and still run on watches that don't do 1hz.
  • vs1hzview.mc I tried to comment as to where to do things, where not to do things, but took a simple approach where I don't just update the seconds at 1hz, I actually do hh:mm:ss. In real code, you likely have a separate space for seconds, and your setClip() will be adjusted for that. I just wanted to get the ball rolling here :). Also, note onEnterSleep() and the code there for 1hz...
  • In onPartialUpdate(), I have a comment about a simple change to make the watch face exceed the power budget, so you can see how that works



Ask questions, suggest other ideas, whatever. That's what this thread is for!

So here's the project! (it might be a bit different than the original one that was lost in the forum update) :

VS1hz-old.zip



NOTE: I should have mentioned this before, but you want to use a 2.3.x SDK for this project!

  • Do you clear the clip again in onUpdate()?

    Not sure, hard to say without code where things go wrong... I was messing around a lot only to find out I had reversed two lines of code by accident causing some coordinates to be out of sync.


    Thanks! this was it. I was doing it on wrong place (at end of the PartialUpdate() DOH:eek:
  • With Jim's help we found that if you have System.println statements in onPartialUpdate, it may cause onPartialUpdate to not execute at all on an actual device.
    This happens if you are debugging the actual device by writing to the log file.

    This works in the simulator which is misleading when trying to figure out why onPartialUpdate doesn't work on the actual device.

    Println statements are very slow on actual devices and causes the onPartialUpdate to exceed its budget and therefor not execute.

    Just posting this scenario here to warn and inform others. ;)
  • Former Member
    Former Member over 7 years ago
    With Jim's help we found that if you have System.println statements in onPartialUpdate, it may cause onPartialUpdate to not execute at all on an actual device.
    This happens if you are debugging the actual device by writing to the log file.

    This works in the simulator which is misleading when trying to figure out why onPartialUpdate doesn't work on the actual device.

    Println statements are very slow on actual devices and causes the onPartialUpdate to exceed its budget and therefor not execute.

    Just posting this scenario here to warn and inform others. ;)


    This actually should not be a problem. Calls to println will not execute on hardware during a partial update, but they should not incur any budget hit, or cause any problems.

    Can you create a bug report for this issue?
  • This actually should not be a problem. Calls to println will not execute on hardware during a partial update, but they should not incur any budget hit, or cause any problems.

    Can you create a bug report for this issue?



    Will do
  • Has anyone managed to get the secondhands working correctly without using the square setClip clipping box. I was hoping to find a solution that only erases the secondhands and not a complete square. Within the Analog example this is not a problem because this watchface uses standard fonts and almost no info. My watchface has custom hands and bitmaps.

    if anyone has some progress on this, please share it ;-)
  • AFAIK you have to use setClip. There is no other way to get it working.
  • Like Hermo said, you need to use setClip(). In the sample I posted, there's a small edit you can do in onPartialUpdate() that will skip the setClip() so you can see what happens if you don't do the setClip(). You'll exceed the power budget, and stop getting onPartialUpdate() calls.

  • hi Jim,

    as i noted in another thread, i've been working (more as a tester) with Jan in trying to get 1 hz HeartRate implemented in Big and Lean, but for some reason, he can't get it to work.

    he tried implementing it similar to how he did the seconds (which works fine).

    he has tried both the following calls:

    SensorHIstory.getHeartRateHistory()
    ActivityMonitor.getHeartRateHistory()

    but neither seem to return a 1-2 sec sampled HR as one finds in the Widget (and your Simple Heart WF).

    it seems that the display itself is updating properly as i sense that it is updating every 72 or so seconds (as opposed to at "00 seconds" which happens for non 1hz elements) which to me suggests that its grabbing a new value when the "plot" in the HR widget is updated, but not actually pulling the most recent measurement at the wrist.

    do you have any suggestions or ideas based on your success with Simple Heart WF?

    thanks in advance for sharing any knowledge or wisdom here. i would love to see Jan's WF have 1hz HR. (it's been a little bit of a slow process for her because he doesn't have a 935/F5 so he relies on me to test out the WF on my 935)

    thanks,
    Derek
  • Both types of SensorHistory only have new data every 1-2 minutes. On some watches, you can get faster updates if you include looking at Activity.Info.currentHeartRate. Basically, look at currentHeartRate first, and if it's null, use history..

    Try my "Simple Heart" if you want to see this in action.
  • thanks for the fabulous tips, Jim. they make perfect sense. i've already tried your Simple Heart watch face and it's wonderful. i just like the formatting/layout that Jan i worked into Big and Lean. but the functionality of yours is superb. great work and thanks for sharing our knowledge and experience with us.

    aside: now if we can only figure out what is up with manually putting a prg file onto our watches, we can test this out! (for some reason both Jan and I are having issues with this now and we never had this happen before... Jan says, even some of his old prg files aren't loading onto his watch. really odd, this was working fine for us just yesterday...)