Testing app settings (working in emulator, crashing with gc/gm)

I wrote a watchface and implemented some user settings for datafields, everything worked fine in the emulator (using the app settings editor) but when changing the settings with GC the watchface crashes...

Is there any way to test this properly? I can only see publishing the app and then testing if it works but that's pretty crappy and also involves uploading many test versions.

CIQ_LOG.TXT gives this:
ERROR: Unhandled Exception
DETAILS: NONE
STORE_ID: d3bdae89b70740408ea84c55f9a81168
CALLSTACK:
UnexpectedTypeException: Expected Number, given Long

I now caught all getProperties to check for null values and non number but that results in it loading the default values all the time... (So apparently it doesn't pass those checks, but I can't figure out why).

I added the <APPNAME>.TXT file in the LOG folder as well but don't see too much extra info.

But the entire process sucks, connecting watch to pc, disconnect, or sync by bluetooth. Rinse and repeat...

Is there any easier way to do this?

For completeness part of my code:
properties.xml:
<properties>

<property id="BackgroundColor" type="number">0xFF0000</property>
<property id="ForegroundColor" type="number">0xFFFFFF</property>
<property id="UseMilitaryFormat" type="boolean">false</property>

<property id="AmPm" type="boolean">false</property>
<property id="Invert" type="boolean">false</property>

<property id="Field1" type="number">1</property>
<property id="Field2" type="number">2</property>
<property id="Field3" type="number">3</property>
<property id="Field4" type="number">4</property>
<property id="Field5" type="number">5</property>
<property id="Field6" type="number">7</property>

</properties>


settings.xml
<setting propertyKey="@Properties.UseMilitaryFormat" title="@Strings.MilitaryFormatTitle">
<settingConfig type="boolean" />
</setting>

<setting propertyKey="@Properties.Field1" title="@Strings.Field1Title">
<settingConfig type="list">
<listEntry value="0">@Strings.None</listEntry>
<listEntry value="1">@Strings.Steps</listEntry>
<listEntry value="2">@Strings.Cals</listEntry>
<listEntry value="3">@Strings.Dist</listEntry>
<listEntry value="4">@Strings.Bat</listEntry>
<listEntry value="5">@Strings.Sunrise</listEntry>
<listEntry value="6">@Strings.Sunset</listEntry>
<listEntry value="7">@Strings.Goal</listEntry>
<listEntry value="8">@Strings.ActMin</listEntry>

</settingConfig>
</setting>

<setting propertyKey="@Properties.Invert" title="@Strings.InvertTitle">
<settingConfig type="boolean" />
</setting>

<setting propertyKey="@Properties.AmPm" title="@Strings.AmPmTitle">
<settingConfig type="boolean" />
</setting>


strings.xml:
<string id="InvertTitle">Invert Color Scheme</string>
<string id="AmPmTitle">Use AM/PM for Time</string>

<string id="Field1Title">Top-Left Field</string>
<string id="Field2Title">Top-Right Field</string>
<string id="Field3Title">Mid-Left Field</string>
<string id="Field4Title">Mid-Right Field</string>
<string id="Field5Title">Bottom-Left Field</string>
<string id="Field6Title">Bottom-Right Field</string>

<string id="None">None</string>
<string id="Steps">Steps</string>
<string id="Cals">Calories</string>
<string id="Dist">Distance</string>
<string id="Bat">Battery</string>
<string id="Sunrise">Sunrise</string>


Program code:
var invert = App.getApp().getProperty("Invert");
var ampm = App.getApp().getProperty("AmPm");
if(invert==null || !(invert instanceof Number)){invert=false;}
if(ampm==null || !(ampm instanceof Number)){ampm=false;}
//var ampmString = "";

var f1 = App.getApp().getProperty("Field1");
var f2 = App.getApp().getProperty("Field2");
var f3 = App.getApp().getProperty("Field3");
var f4 = App.getApp().getProperty("Field4");
var f5 = App.getApp().getProperty("Field5");
var f6 = App.getApp().getProperty("Field6");


if(f1==null || !(f1 instanceof Number)){f1=1;}
if(f2==null || !(f2 instanceof Number)){f2=2;}
if(f3==null || !(f3 instanceof Number)){f3=3;}
if(f4==null || !(f4 instanceof Number)){f4=4;}
if(f5==null || !(f5 instanceof Number)){f5=5;}
if(f6==null || !(f6 instanceof Number)){f6=6;}
App.getApp().setProperty("BackgroundColor", 0x000000);
App.getApp().setProperty("ForegroundColor", 0xFFFFFF);

var bgColor = App.getApp().getProperty("BackgroundColor");//Gfx.COLOR_BLACK;
var fgColor = App.getApp().getProperty("ForegroundColor");//Gfx.COLOR_WHITE;
if(bgColor == null || !(bgColor instanceof Number)){bgColor = 0x000000;}
if(fgColor == null || !(fgColor instanceof Number)){fgColor = 0xFFFFFF;}

if(invert){
bgColor = App.getApp().getProperty("ForegroundColor");//Gfx.COLOR_WHITE;
fgColor = App.getApp().getProperty("BackgroundColor");//Gfx.COLOR_BLACK;;//Gfx.COLOR_BLACK;
}
  • Maybe I missed it, but what watch and phone type..
  • Maybe I missed it, but what watch and phone type..


    Oh, I own a forerunner 935 myself and got a report from a crash on the Fenix 3...

    I have been able to reproduce it on my 935 as well so it seems a general thing.

    As it worked in the emulator I kinda assumed it worked for real as well :/

    *EDIT*

    Apparently the values using getProperty were returned as Long instead of Number? (Is my best guess at least, causing type errors).

    I seem to have fixed it by now using this code to get a number property:
    function getNumberProperty(key, value){
    var result = App.getApp().getProperty(key);

    if( result instanceof Long ){ result = result.toNumber(); }
    else if( result instanceof String){ result = result.toNumber(); }

    if(result == null){ result = value; }
    return result;
    }
  • Sounds like you hit what's talked about in the New Developer FAQ, point 10. When that came up, numbers were sometimes returned as floats. There's a simple wrapper function there that makes sure a number is seen as a number.
  • Sounds like you hit what's talked about in the New Developer FAQ, point 10. When that came up, numbers were sometimes returned as floats. There's a simple wrapper function there that makes sure a number is seen as a number.


    Yeah, I do feel a bit silly now ;) Even though this was using the garmin express application, not the android mobile app...

    Anyway, another lesson learned... many more to go!
  • Initially, it was an android thing when app settings was first introduced, and a few of us posted various versions of the wrapper function, then Brandon added it to the FAQ. Since those days, I've always just used it in everything, so if something new came up in GCM/iOS or GE, it would be handled. It's not uncommon that folks just starting out miss it, but it's an easy fix. :)