My color options works on the simulator but not on watch when I uploaded it to the store.

I have recently published my first watch face "Aviation Time" to the IQ store.  The first version was working fine, but I wanted to add some more color options.  The color changes work well in the simulator, however once uploaded to the store, the new options fail to take.  I can select, say a new background color and hit save, but the changes never take.  Also, the settings revert back to what the watch is showing.  

Any thoughts?

The full code is uploaded to:

github.com/.../AviationTime

  • You sir, are a life saver!  

    I had similar results with the 1000ms.  Unfortunately I had nothing to compare it to and didn't know that was heavy.

    I moved a lot of stuff to the *App.mc file.  Most importantly the onSettingsChanged() is called and assigns the changes in the *App.mc file.  This made the settings calls happen much less.  Part of this was defining my variables outside of the class definition (I didn't know you could do this).  I also added the calls to the initialize and onShow parts so that it initializes better.

    This was the guidance I needed and am very grateful.

  • 1. you don't need dc.clear() onUpdate because you have it in Background.draw

    2. in Background.draw  you still call getProperty

    3. delete not used function if you don't use it  (e.g. onEnterSleep)

    4. findDrawableById costs a lot too, you have a lot of free memory so assign it to members in onLayout (after insetLayout(Rez.Layouts.WatchFace(dc));)

  • Thank you for your patience and instruction.  I'm essentially trying to learn 2 languages at once: Monkey C and its' lingo.  Unfortunately, I have yet to find an on-line course to learn Monkey C, so I am learning by examples, the Connect IQ Reference Manual, and a lot of searches.

    1. It was my understanding that the dc.clear() in the onUpdate was required to erase the face using the background graphics,  making sure images such as the old minutes were cleared off before I drew the new ones.  Does the background draw on every update, or does my changing of the values (setText()) erase what is already there?

    2. and 3.  The background.mc is a copy/paste of the sample provided by Garmin.  It worked, so I left it as is.  Unfortunately, I have not figured out exactly how or when it is called (I believe it only gets called when setLayout() is called).  I also cannot find which of the initial functions are required (onStart, onStop, getInitialView, getApp, onLayout) nor where they are required to be.  I can delete til crash and find out the fun way.  I will re-read the Hello Monkey C section, too.

    4.  That make sense.  Side question, would including $. (bling) help with efficiency?

    Thanks again,

  • 1. you use View.onUpdate(dc); it means mlayout is drawn and first controls in layout is background so it should clears screen too. But comment it and test Slight smile

    2. you can modify pasted code :) add another globals for background property and read it in onSettingsChange (all properties should be read only when necessary and not in in drawing/ado/partial/etc).

    flow app

    https://developer.garmin.com/connect-iq/api-docs/Toybox/Application/AppBase.html

    flow view

    https://developer.garmin.com/connect-iq/api-docs/Toybox/WatchUi/View.html

    onShow()/etc. is "virtual func" and system has it in parent and it calls itself version - comment it and test

    3. $ makes code bigger and in my opinion (after tests in sim/profiler ) is even slower - even though doc says is more efficiency (I think it was faster somewhen, when there was no symbols for all vars and doc was not updated).

  • So...I seriously owe you a coffee.  Do you have a pay app?  Your suggestions made a huge difference in my efficiency.  Making the drawableById barely made a blip in memory usage and dramatically reduced my calls.

    Thanks!

  • No, I don't have pay app :)

    1. findDrawableById returns WatchUi.Drawable  so you should use simple e.g.

    view = View.findDrawableById("TimeLabel");

    2. you dont use dc in drawTime(dc)

    3. still exist empty onHide. onStop ...

    4 change case to if/else if /else this black horse

    5. you duplicate sys func e.g. getApp

    6. you can save mem/proc if you move all drawXX into onUpdate. I know, function organise code but above all they useful when you call them from more than one place. Each func call cost...

    BTW check your code e.g.:

      //Display Alarm Info
            function drawAlarm(){

                //See if an alarm is set

                var alarmString = "A";
                var alarmStr = Lang.format("$1$", [alarmString]);// *********************** alarmStr not used


                alarmLoad = System.getDeviceSettings().alarmCount;// *********************** alarmLoad why is global??

                if (alarmLoad != 0) {
                    alarmString = "A";
                } else {
                    alarmString = " ";
                }

                alarmDisplay.setText(alarmString);
            }

            //Display notification information
            function drawNote(){

                //See if there are any system notices

                var noteString=" ";
                var noteStr = Lang.format("$1$", [noteString]);// ***********************  noteStr not used
                
                noteLoad = System.getDeviceSettings().notificationCount;// *********************** noteLoad why is global??

                if (noteLoad !=0) {
                    noteString = "N";
                } else {
                    noteString = " ";
                }
                noteDisplay.setText(noteString);
            }

    can be:

    function onUpdate(dc) as Void
    {
                var    ds = System.getDeviceSettings();
    //Display Alarm Info
                alarmDisplay.setText(ds.alarmCount            ? "A" : " ");
    //Display notification information            
                noteDisplay.setText(ds.notificationCount     ? "N" : " ");
    }

  • Sorry for the break in my education...I had to go to work.  Thank you for the clean-up suggestions. I have done most of them.

    Question: I changed my code to a single getApp():

        app =  Application.getApp();

    and then ask each item individually for its' information:

        myBgColor =  app.getProperty("BackgroundColor");

        myClockColor = app.getApp().getProperty("ClockColor");

    Does that execute the getApp() once or each time app is used (twice in this example) ?

  • please don't ask about such trivial thing, it's your homework Slight smile

    btw. your code won't run for new devices

  • Drooling face So...

    I switched to getValue but I am unable to figure out how to do the bulk call.  I could do the generic

        appSets = Properties.getValue;

    but I cannot pull out the individual pieces and had to revert to:

        clockColorNum = Properties.getValue("ClockColor");
    I tried google for an answer (why are all the examples 5+ years old and still using getProperty(), including Garmin's?) and then I tried brute force...

        clockColorNum = appSets("ClockColor");
        clockColorNum = appSets.("ClockColor");
        clockColorNum = appSets(ClockColor);
        clockColorNum = appSets.ClockColor;
    You get the idea. So, which magical combination am I missing? Is this where you tell me my Venu 2 is OBE and is being deprecated?
    Thanks again, again.
     
  • 1. you can use bulk call because... because no such api, so you have use single call for each property:

    using Toybox.Application.Properties    as PRP;
    value = PRP.getValue(key);

    2. if owner of API says "is deprecated from 4.0" you should use (probably Garmin hasn't remove it yet but it may happen in any moment with firmware update). In your manifest is minApiLevel="3.2.0" so you should use PRP.getvalue and you will be sure software will run without problems even if Garmin update software.