02-26-2019 09:12
02-26-2019 09:12
I'm having a strange issue. I made an update to my Clarity clockface and at the same time updated it to SDK 3. I received a couple of emails from android users saying their version was no longer displaying properly. For others it seems to be fine.
Now in doing further testing I can no longer load the clockface myself!
I've created two private clock faces. One built with SDK 2 and one with SDK 3 both with identical code.
SDK 2
https://gam.fitbit.com/gallery/clock/93be9a9c-25ae-4fd3-86ef-8415739b24cc
SDK 3
https://gam.fitbit.com/gallery/clock/23ae3f5c-fdc5-474f-b1e4-8db85eccb5b4
I can load the SDK 2 version fine, but the SDK 3 version fails.
Both work fine with the simulator. If I try and sideload the SDK 3 is fails with "Sideload of app failed. Internal Error." I can sideload the SDK 2 version fine. Also if I first sideload the SDK 2 version and then sideload the SDK 3 version it works! Which I think explains why I was able to upgrade by existing Clairty clockface once it was approved for public distribution (since I was already running the SDK 2 version).
Any help most welcome!
Answered! Go to the Best Answer.
02-28-2019 11:59
02-28-2019 11:59
I agree. I'm currently throwing together a FAQ on SDK development. Here's a foretaste:
Don't initialise anything you don't have to immediately. For example, initialise elements for secondary screens only when they’re about to be displayed. If you structure such code into objects, you can also reduce memory use.
getElementById(), getElementsByClassName(), etc, can be quite slow. If your .gui is large but well structured, minimise calls to document.getElementById by using the element’s immediate parent, rather than ‘document’, if there are several elements beneath that parent. This will spare the startup code from having to look through the whole DOM every time.
This is a big job. Before getting carried away with it, it might be wise to comment out some chunks of code, variables and/or UI elements that aren't initially required, just to verify the hypothesis (and maybe narrow down focus areas).
02-26-2019 09:28
02-26-2019 09:28
I'd definitely remove gallery versions and sideloaded versions, then make sure you're still having the issue.
Have you checked the new migration guide for hints on changes? https://dev.fitbit.com/build/guides/migration/
02-26-2019 09:51
02-26-2019 09:51
I definitely still have the same problem with so sideloaded versions.
I'm not 100% sure what you mean by remove gallery versions: I installed a random other clockface before trying to load the new version (is that what you mean?) - and still had the problem. Of you you mean remove all the private versions from the gallery? (But these all have different UUIDs I think).
I did look at the migration guide and saw nothing obvious. It's a fairly standard clock face which shows activity details etc and handles a second timezone. I do save settings to a cbor file (tried changing to to json but no joy).
02-26-2019 11:56
02-26-2019 11:56
The behaviour you described sounds like what happens if a clockface doesn't start within the allowed 10 seconds. Unfortunately, SDK3 code seems to be a fair bit slower to start (but is much faster when running). Some of my apps take almost 10 seconds just to compile, so they don't get much time to initialise themselves before the OS kills them. Your clockfaces shouldn't suffer from this problem, but maybe think about whether you've got any slow startup code in there — especially blocking while waiting for comms or lengthy storage operations. (Loading a small .cbor should be fine.)
02-27-2019 06:26
02-27-2019 06:26
Thanks for your advice. I'll start looking at this and see if I can figure out the timings.
This is my first ever javascript programming so it is easily possible I made a rookie mistake (its a long time since I coded seriously - we're talking fortran!). In particular I copied the messaging code without fully understanding it all!
One thing I do is to send the current stored settings to the companion if/when it is alive. This is so that and settings changed on the watch itself are made visible in the settings on the phone. I guess the companion will always run when the clockface is installed.
I've put the code on GitHub in case anyone has time to take a quick look.
https://github.com/apgr/FitBit-Clarity
02-27-2019 08:32
02-27-2019 08:32
Here is a screen cap of the SDK2 version being sideloaded into my versa...
02-27-2019 12:02
02-27-2019 12:02
Alas, the companion comes and goes. That shouldn't matter if you've coded your comms not to make any assumptions about its availability. However, if your device code blocks (eg, loops) waiting for the companion socket to open, you're asking for trouble. Hopefully you didn't do that!
02-27-2019 12:28
02-27-2019 12:28
I think I'm OK on this. The relevant code is
//------------- Companion is alive ---------------------------------
messaging.peerSocket.onopen = () => {
console.log("Companion is awake.....");
sendValue("DST", settings.DST);
sendValue("TZtoggle", settings.TZtoggle);
sendValue("TimeZone", settings.TZindex);
sendValue("secondTimeZone", settings.secondTimeZone);
sendValue("Activity-slider", settings.Actopacity*100);
sendValue("slider", settings.TZopacity*100);
};
I assume that this code segment is only executed if the open event happens (although this is the area I really am most unsure about).
02-27-2019 12:41
02-27-2019 12:41
Yes, that looks okay.
I just had a quick squiz at your source code (without actually trying to run it). You do have a LOT of startup code in there. getElementbyId (etc) are very slow. In addition, tile list items actually take a while to be initialised (even before your code gets a chance to run), and you've got quite a few of those. This is strengthening my concern about slow start-up time.
Before embarking on any major refactoring, have you verified that you're not out of memory? Can you get app/index.js to console.log('hello') at the very start?
02-27-2019 13:16
02-27-2019 13:16
Thanks - I really appreciate you taking the time to help! I added the colsole.log('hello") at the start
I then sideloaded with SDK2 and get the following...
sdk2
If I then immediately switch the SDK3 I get
If I first delete the sideloded app and try to sideload under SDK3 I get
where the only new line of output is the red one.
02-27-2019 13:26
02-27-2019 13:26
I'd still check memory, but that really seems like a startup time issue to me. After you deleted the initial sideloaded app and then pushed a new version, the watch would have needed to recompile the code prior to running it. If that takes 10+ seconds, Bad Things can happen. SDK3 code seems to take longer to compile on the watch than does SDK 1 or 2 code.
I'd check memory before doing anything drastic.
02-27-2019 13:41
02-27-2019 13:41
Thanks - I'll follow your suggestions and report back...
02-28-2019 05:28
02-28-2019 05:28
I just added lines to check memory on startup and then every second in the clock loop. With SDK3 I get
I let it run for a few minutes and it seems to hover around 41-43k. So I think ti is the startup time rather than memory.
02-28-2019 11:59
02-28-2019 11:59
I agree. I'm currently throwing together a FAQ on SDK development. Here's a foretaste:
Don't initialise anything you don't have to immediately. For example, initialise elements for secondary screens only when they’re about to be displayed. If you structure such code into objects, you can also reduce memory use.
getElementById(), getElementsByClassName(), etc, can be quite slow. If your .gui is large but well structured, minimise calls to document.getElementById by using the element’s immediate parent, rather than ‘document’, if there are several elements beneath that parent. This will spare the startup code from having to look through the whole DOM every time.
This is a big job. Before getting carried away with it, it might be wise to comment out some chunks of code, variables and/or UI elements that aren't initially required, just to verify the hypothesis (and maybe narrow down focus areas).
02-28-2019 12:20
02-28-2019 12:20
Thanks - I look forward to seeing your end product!
In the meantime my immediate problem has been solved since an SDK2 build of Clarity has just been approved and released.
However I will plug away at this and see what I can do following your suggestion of commenting out sections.
03-01-2019 06:56
03-01-2019 06:56
It's fixed! In the end the key was exactly what you suggested - namely to minimise calls to document.getElementById by using the element’s immediate parent. It now sideloads comfortably...
I still have to try loading it from the gallery but I am sure it will now be fine.
Thanks again for taking the time to help. I really appreciate it!
03-01-2019 11:35
03-01-2019 11:35
Excellent! I'm relieved that I didn't send you on a wild goose chase.
I haven't noticed any performance or behaviour differences when loading from debug bridge vs. gallery, so you should be fine I think.