How to put values in arrays in the watch storage?

Hi,

I would like to have values changed in a widget and stored in an array, even if the widget is closed in the watch storage and recall these values as soon as the widget is startet,

so that the user could continue.

Something like a counter that continues counting from the latest active value, when the widget was used.

How can I do this? Any constraints to consider?

A small example with guidance where to put what would be very helpful...

Thanks!

  • Application.Storage.getValue() and Application.Storage.getValue()

    You can use setValue() in onStop() and getValue() in onStart()

    Application,setValue(myKey,[1,2,3,4]);

    for example.

  • I tried to put a whole array to the storage but I receive an error message. What went wrong?

     public var myArray =new [10];

    ....

    myArray[2]=31;

    ...

        function onStop(state as Dictionary?) as Void {
          Storage.setValue("array", myArray);               
        }

    ....

    function onStart(state as Dictionary?) as Void {
    var myArray2 = Storage.getValue("array");         
       System.println(myArray2[2]);
        }


    Error message:

    Error: Unhandled Exception
    Exception: UnexpectedTypeException: Expected Object/Array/Dictionary/ByteArray, given null

  • how to store dates in the watch storage?

    tried:

    ...

      today = Gregorian.info(Time.now(), Time.FORMAT_MEDIUM);
    dateString = Lang.format(
        "$1$:$2$:$3$ $4$ $5$ $6$ $7$",
        [
            today.hour,
            today.min,
            today.sec,
            today.day_of_week,
            today.day,
            today.month,
            today.year
        ]
    );

    ...

      Storage.setValue("date", today);       

    Error Message:

    Error: Unhandled Exception
    Exception: UnexpectedTypeException: Given value cannot be serialized
    Stack:
      - onTap() at C:\...eclipse-workspace\Date1\source\MyInputDelegate.mc:58 0x100004f8
      - handleEvent() at C:\grmn\prj\DI\toolchain\mbsimulator\submodules\technology\monkeybrains\virtual-machine\api\WatchUi.mb:1077 0x30002403      

  • Not all data types can be put into storage, and what you're trying to do with "today" isn't one of them.

    From the API Doc:

    Values can be of the following types:

    If I want to store a date i usually do something like

    var now=Time.now().value();

    Storage.setValue(key,now).

    "now" is a Number that's what's often called "unix time" 

  • Ok I understand. I guess this is a kind of basic requirement to store a lot of data on the watch, therefore it is a bit surprising that array is not possible.

    Is there another efficient way, to create a kind of "mass-data storage" in the watch. I need the status of 50+ elements permanently saved and requested upon load and stop of a widget. Do I need to create several single keys? Is there a "numerical" way with a for-loop?

  • But according to the docs, you can store arrays and dictionaries in Storage. Jim was saying that you can't store a Gregorian.Info in Storage.

    If you wanted to store array items individually for whatever reason, you could make the array index part of the key. But there would be additional overhead with such a solution, in terms of storage space, memory and code.

    [https://developer.garmin.com/connect-iq/api-docs/Toybox/Application/Storage.html#setValue-instance_function]

    Values can be of the following types:

    Values can also be of type Array or Dictionary containing the above listed types, excluding BitmapResource and AnimationResource. There is a limit on the size of the Object Store that can vary between devices. If you reach this limit, the value will not be saved and an exception will be thrown. Also, values are limited to 32 KB in size.

  • Arrays a possible.  It' s that you can store an object type of ""Gregorian.Info", be it by itself, or in an array,

  • Which is the best order for calling the array in interaction with the watch storage?

    First I need to create a new array, but later I need to call the values from the saved array from the watch storage (which is in the first run empty)

    Can I clarify the array definition as public to be able to used in in various functions?

       function onStart(state as Dictionary?) as Void {

    public var myArray = Storage.getValue("array");       

     I receive an error:

    BUILD: ERROR: venusq: C:\Users\...\eclipse-workspace\Date1\source\Pilot1App.mc:18: extraneous input 'public' expecting {'++', '--', '+', '-', '~', '!', 'Method', 'var', 'while', 'do', 'for', 'if', 'switch', 'try', 'throw', 'break', 'continue', 'return', 'true', 'false', 'null', 'NaN', 'new', '[', '{', '}', '(', ':', '$', INTNUMBER, HEXNUMBER, OCTALNUMBER, FLOATNUMBER, ID, STRING, CHAR}

    What would be a good workaround in general?

    1.) Define array in Delegate environment (is size definition necessary e.g. [10])

    2.) Change content of array in case of event (e.g.Delegate:  ontap, onclick)

    3.) Store the array on the watch storage (in Delegate or onStop in App environment?)

    4.) Recall the array with onStart (App environment)

    5.) Use / Change the values in case of an event (--> 3.)

    Where is it best to define / initialize the array / size? How to make it public to be used in several functions?

  • I think you are confusing public and global variables 

    if you want something global, declare it like this:

    var myArray=[];
    
    class o2App extends Application.AppBase {
    ..
    ..
    }

    You can reference myArray anywhere in your app this way

  • Is it possible to initialize an array with predefined values?

    e.g. var myArray[ ] =2; or do I need a for..next loop to fill?

    If have issues using the arrays & storage (especially in the initializiation mode):

    I got an error:

    Error: Unhandled Exception
    Exception: UnexpectedTypeException: Expected Float/Object/Array/Dictionary, given null
    Stack:
      - onStart() at C:\Users\...\eclipse-workspace\...\source\Pilot1App.mc:34 0x100002a6 (see bold in source code)

    ...

    var status =new [20];
    var position;

    class Pilot1App extends Application.AppBase {

        function initialize() {
            AppBase.initialize();
        
        }

     
        function onStart(state as Dictionary?) as Void {
     
      status=Storage.getValue("status");
     
     
      if (status == null) {
     
       for (var i = 0; i < 20; i++) {
       
         status[i]=0;
         }
         }
     
      position = Storage.getValue("position");
     
      if (position == null) {position=0;}
     
       
        }


        function onStop(state as Dictionary?) as Void {
       
       Storage.setValue("status", status);
       Storage.setValue("position",position);   
                  
        }