More "App Settings" questions for datafields

I'm having trouble getting my complex datafield to reflect/show a setting change after I modify and send it using the app settings editor in Eclipse (says "Settings sent successfully"). I send the updated setting while the datafield is running in the simulator. I've read as many of the other threads about this topic, but they all seem to relate to CIQ apps and widgets.

As far as I can tell my resource file is written correctly, and my .getProperty("maxhr_prop") call in the initialise() function correctly retrieves the default value defined in the resource file as confirmed with a console output "println" and displayed on the datafield in the simulator. Actually I've noticed that modifying the value in the resouce file isn't always updated. The old value seems somewhat sticky. This is on mac.

My datafield code also does a .getProperty call in the compute() function, however the value that I output using both a console output and displayed on my datafield on the simulator never changes from the default value in the resources file (properties.xml).

Here's the resource file
<resources>

<properties>
<property id="maxhr_prop" type="number">165</property>
</properties>

<strings>
<string id="maxhr_title">Maximum Heart Rate</string>
<string id="hr_out_of_range_msg">Max HR must be between 100 and 230</string>
</strings>

<settings>
<setting propertyKey="maxhr_prop" title="maxhr_title">
<settingConfig type="numeric" required="true" min="100" max="230" errorMessage="hr_out_of_range_msg"/>
</setting>

</settings>
</resources>


and the code (this is the "app" class, there is a separate "view" class):

using Toybox.System as System;
using Toybox.Application as App;

class hr_tiz_data {

// public data
var timertime;
var maxHr;
var hr;
var hr_pmax;
var ave_hr;
var ave_hr_pmax;
var zone;
var timer_paused;
const NumZones = 5;
hidden var zoneLowerBound = [NumZones];
var secondsInZone = [NumZones];

function initialize() {
//maxHr = 182;
maxHr = App.getApp().getProperty("maxhr_prop");
System.println("\nMax HR=" + maxHr.format("%d"));
zoneLowerBound = [0, maxHr * 0.77, maxHr * 0.88, maxHr * 0.92, maxHr * 0.95];
secondsInZone = [0, 0, 0, 0, 0];
timertime = 0;
timer_paused = true;
}

function compute(info) {

maxHr = App.getApp().getProperty("maxhr_prop");
System.println("\nMax HR=" + maxHr.format("%d"));

if (info.timerTime != null) {
// Check if user has paused the timer
timer_paused = (info.timerTime == timertime);

if (!timer_paused) {
timertime = info.timerTime;
}
}


- should I be calling "onSettingsChanged()" or is that only for apps and widgets?
- is it expected that datafield App settings are modified while running (i.e. user with GC mobile app), and changes need to be checked for, or should datafields just get the values once at the start?
- if App settings should be checked while running, is there a better place than the compute() function?

Confused - thanks for your help!
  • Former Member
    Former Member over 9 years ago
    Your property declaration seems fine to me. I can't explain why you shouldn't see the new value when you change it in the App Setting Editor.

    As for your other questions: you can use onSettingsChanged in a data field in the same way you'd use it in widgets, apps and watch faces. I don't think it's good design to read the setting every second in the compute method. In stead you should read it once and store the value.
    If you want changes in the settings to take effect immediately, I'd recommend you use onSettingsChanged. However, if you're just using settings for hr zones, which usually don't change that often, you might choose not to implement any settings change functionality at all.
  • Thankyou TeunMo! I have come to the conclusion that the App settings editor is quite buggy for the mac. I have been trying multiple combinations but not once have I seen my setting changed while the datafield is running in the simulator, and there have been many simulator crashes.

    I agree for HR zones, I only really need to load them once at startup, and not check for updates, but I am using this as a learning example for future use, so I would like to see the settings updated while running the program.

    I have another couple of questions:
    1. In the simulator environment, are updates sent from the app settings editor meant to be persistent for multiple recompile / re-run of my program? Or are the defaults loaded from the resource file every time I run it, and any updates using app settings editor only valid while the datafield is running?

    2. What is the correct way to call onSettingsChanged()? I mean, where in the program structure / scope should I call it? I know this is a newby OOP related question but I am new to OOP. The Garmin sample program "ObjectStore" shows onSettingsChanged() called within the class that extends App.AppBase. Is that necessary, or can I call it in my class? I don't understand the link between the onSettingsChanged() function and its scope / visibility within classes.

    Thanks again for your help guys.
  • Former Member
    Former Member over 9 years ago
    1. In the simulator environment, are updates sent from the app settings editor meant to be persistent for multiple recompile / re-run of my program? Or are the defaults loaded from the resource file every time I run it, and any updates using app settings editor only valid while the datafield is running?


    In the simulator, the settings are stored in a settings file, just like on a real device. You can find the settings file in the %TEMP%\Garmin\Apps\SETTINGS folder (on windows, it's something similar on a mac). When you restart your app it will just read from that file. To reset the settings, you have to remove the settings file.

    2. What is the correct way to call onSettingsChanged()? I mean, where in the program structure / scope should I call it? I know this is a newby OOP related question but I am new to OOP. The Garmin sample program "ObjectStore" shows onSettingsChanged() called within the class that extends App.AppBase. Is that necessary, or can I call it in my class? I don't understand the link between the onSettingsChanged() function and its scope / visibility within classes.


    AppBase.onSettingsChanged is what gets called when the settings are changed, so that's always your starting point. It's simply a method in that class. You can find multiple working implementations on this forum. For instance in this thread.
  • ok thanks again. If this is how the settings file is supposed to work, it is definitely not working for me. It is never updated, even though the settings editor claims it is. Also I cannot get the onSettingsChanged() to execute - ever - no matter what I try.

    Thanks for the link, I hadn't read that thread because the title referred to fonts, but this is gold! in terms of understanding how to call onSettingsChanged().
  • Your property declaration seems fine to me. I can't explain why you shouldn't see the new value when you change it in the App Setting Editor.

    As for your other questions: you can use onSettingsChanged in a data field in the same way you'd use it in widgets, apps and watch faces. I don't think it's good design to read the setting every second in the compute method. In stead you should read it once and store the value.
    If you want changes in the settings to take effect immediately, I'd recommend you use onSettingsChanged. However, if you're just using settings for hr zones, which usually don't change that often, you might choose not to implement any settings change functionality at all.


    Can somebody / Garmin please confirm that this (blue text above) actually works for datafields? I suspected the mac simulator was buggy so I set up Eclipse/SDK/IDE etc on a Win7 PC last night and the behaviour is identical!! - A good thing but I want it to work if its supported. I basically coded it as per the link that TeunMo gave earlier in this thread.

    Thanks all
  • I can confirm that onSettingsChanged() is getting invoked for data fields that I've worked on.

    Travis
  • One thing to note here. You don't need "onSettingsChanged()" for user settings. You can changes stuff from GCM/GE without it.

    What "onSettingsChanged()" does, is alert you if user settings change while you're running so you can adjust.

    If you don't have an "onSettingsChanged()", and you're running, you just won't see the new settings until next time your stuff runs.

    Get things to work without thinking about "onSettingschanged()" and then figure out how the new settings would be used in something that is currently running. If it's changing colors, that's easy, but if it's changing the basic mode of your DF, you may want to wait until the next time the DF is used to change to that setting...
  • Thanks Travis and Jim.

    Jim yes that is my understanding now too based on earlier discussion in this thread - so while I probably don't need to adjust user settings for a datafield while its running, I just wanted to learn how to use it.
  • Thanks very much to Travis who worked out my problem. It turns out the simulator / App Settings Editor has a bug caused by having a space in the program name. With the space removed, I can update user settings. They stay persistent between app runs, and also onSettingsChanged() executes when expected.

    Essentially it looks like with a space in the program name, the App Setting Editor is not communicating with the watch simulator. Rename the project by right clicking on the top level project name in the Eclipse file manager and select the "rename" menu, then remove the space.

    The same bug and the fix are also present under Mac and windows version of the SDK.

    Garmin can you please report this and get it fixed - thanks!
  • Thank you thank you thank you

    Thanks very much to Travis who worked out my problem. It turns out the simulator / App Settings Editor has a bug caused by having a space in the program name. With the space removed, I can update user settings. They stay persistent between app runs, and also onSettingsChanged() executes when expected.

    Essentially it looks like with a space in the program name, the App Setting Editor is not communicating with the watch simulator. Rename the project by right clicking on the top level project name in the Eclipse file manager and select the "rename" menu, then remove the space.

    The same bug and the fix are also present under Mac and windows version of the SDK.

    Garmin can you please report this and get it fixed - thanks!



    So sad that this is hidden away. I've spent days wondering why this just doesn't work. Working with Garmin is a never ending joy hey.