Made some progress on publishing complications!

This is with the 4.2.0 beta1 SDK, the f7 System 6 preview device, and one of my watch apps.  Here's what I see in the sim under Simulation>Complications, when I select the complication.  The app is running in the sim at this point.  The image is the icon I supplied for the complication.  53.10 is the temperature as seen by the app.  A first step!

  • Today, subscribeToUpdates() doesn't even compile!

    Maybe not if you take the examples in the docs literally. One glaring mistake (not just a typo) is that the docs claim getComplications() returns a list of Complications.Id, when in fact it returns a list of Complications.Complications.

    I got the following code to compile and run with default type checking, although onComplicationChanged() is never called no matter how many times I publish a new value. EDIT: It's probably because I need to update the complication using a background process, which I didn't bother to do yet.

    import Toybox.Application;
    import Toybox.Lang;
    import Toybox.WatchUi;
    import Toybox.Complications;
    
    class ComplWatchFaceApp extends Application.AppBase {
    
        function initialize() {
            AppBase.initialize();
        }
    
        var complication1 as Complications.Complication or Null;
        var complication2 as Complications.Complication or Null;
    
        // onStart() is called on application start up
        function onStart(state as Dictionary?) as Void {
            var iter = Complications.getComplications();
            // iterate over them
            var complication = iter.next();
    
            while (complication != null) {
                System.println("short label: " + complication.shortLabel);
                System.println("ID: " + complication.complicationId.toString());
                if ("label 1".equals(complication.shortLabel)) {
                    complication1 = complication;
                    // System.println(complication.getUuid());
                }
                if ("label 2".equals(complication.shortLabel)) {
                    complication2 = complication;
                }
                complication = iter.next();
            }
            Complications.registerComplicationChangeCallback(self.method(:onComplicationChanged));
            if (complication1 != null) {
                Complications.subscribeToUpdates(complication1.complicationId);
                System.println("subscribed to complication");
            }
        }
    
        function onComplicationChanged(complicationId as Complications.Id) as Void {
            // Identify the complication being updated
            System.println("complication updated");
            //if (complicationId == complication1.complicationId) { // <== bug which is also present in garmin example
            if (complicationId.equals(complication1.complicationId)) {
                // Get the complication information
                try {
                    var data = Complications.getComplication(complicationId);
                    System.println("Updated data = " + data.value);
                } catch (e instanceof Complications.ComplicationNotFoundException) {
                }
            }
        }
    
        // onStop() is called when your application is exiting
        function onStop(state as Dictionary?) as Void {
        }
    
        // Return the initial view of your application here
        function getInitialView() as Array<Views or InputDelegates>? {
            return [ new ComplWatchFaceView() ] as Array<Views or InputDelegates>;
        }
    
    }
    
    function getApp() as ComplWatchFaceApp {
        return Application.getApp() as ComplWatchFaceApp;
    }

  • As I've said throughout this thread, the doc on this is pretty bad....

  • As I've said throughout this thread, the doc on this is pretty bad....

    Yep, but subscribeToUpdates() compiles, and as you'll see below, actually works.

    I changed my publisher code to implement a background process which updates the complication value.

    I also fixed a bug in my update callback (that was present in the example), changed a detail in my System.println() statement, and everything works as expected. The details of the docs may be wrong, but the general idea is there.

        function onComplicationChanged(complicationId as Complications.Id) as Void {
            // Identify the complication being updated
            System.println("complication updated");
            if (complicationId.equals(complication1.complicationId)) {
                // Get the complication information
                try {
                    var data = Complications.getComplication(complicationId);
                    System.println("Updated data = " + data.value);
                } catch (e instanceof Complications.ComplicationNotFoundException) {
                }
            }
        }

    The point is I'm able to publish complication data and subscribe to updates (despite your implication that subscription is impossible.)

    My point still stands:

    - subscribing to a complication (or even remembering which complication the user selected from the list returned by getComplications) is based on Complications.Id

    - Complications.Id consists of native type, app UUID, and complication resource ID/index

    - The complication resource ID/index is significant (contrary to what you said), since changing it will break existing subscriptions (and it will also break saved Complication.Ids). Even if you're not subscribing, you're still probably going to save the user's selected complication ID(s), unless you plan on saving the shortLabel or longLabel instead.

    So the app UUID and complication resource index are used (as part of the complication ID), even if CIQ apps don't have access to their specific values (since they're private members of Complications.Id with no accessor functions).

  • I'll be honest and say I didn't bother to read the thread (beyond the comment I originally replied to), but I can't believe you've been looking at this for two weeks and you didn't try to get "subscribe to complication updates" working. I feel like that's the whole point of the feature, unless you feel like constantly iterating through getComplications() in your WF, or holding references to complications of interest for the lifetime of the app.

    As I've said throughout this thread, the doc on this is pretty bad....

    Yet somehow I was able to get subscribing to complication updates to work.

    Aren't you the one normally telling people not complain about bugs, errors in docs, etc.? Funny how it's different when the shoe's on the other foot.

    I filed a bug report about Enduro's simulator.json a few years ago. You initially misunderstood my post and condescendingly explained a bunch of stuff I already put in the original post. Then Garmin acknowledged the bug and said they'd fix it. Recently (years after the bug report), I noticed it still wasn't fixed so I politely asked Garmin to fix it. You replied again and told me I should just manually edit simulator.json if it mattered to me so much (missing the point that not only did I want simulator.json to be correct, I also wanted to know what the correct value was for the actual product.)

    Maybe you should manually edit the beta SDK's HTML documentation to fix all the bugs if it matters to you so much.

    Similarly, you condescendingly told me I was wrong about the resource ID and app UUID (but I was right), and implied that I didn't understand where complication IDs come from (but I do understand), as well as suggesting that I don't understand what a Complications.Id is (but I actually understood better than you did, before I even wrote a single line of code to test this stuff.)

  • Just to follow up on this thread, I tried storing a Complications.Id using Storage.setValue() and got the following error message, which was not entirely unexpected:

    Error: Unhandled Exception
    Exception: UnexpectedTypeException: Given value cannot be serialized

    That's funny because it means not only does the documented example of reading a Complications.Id from storage and subscribing to updates not make any sense at all, it also means there's no way to remember which non-native complication(s) were selected by the user in a previous run of the app except to remember the shortLabel and/or longLabel, or perhaps the index of a complication within the list returned by getComplications() (neither of those solutions seems like a good idea).

    Hopefully this is something Garmin fixes / implements before complications are production-ready.

    (This doesn't change the fact that Complications.Id clearly consists of native type, app UUID and resource ID, and Complications.Id is used to subscribe to updates and uniquely identify complications, even if we have no way of storing Complications.Id today. Obviously Garmin intends for it to be possible.)

    This is the relevant part of the docs:

    ~/Library/Application Support/Garmin/ConnectIQ/Sdks/connectiq-sdk-mac-4.2.0.beta1-2022-10-11-bff57b73c/CoreTopics.html#subscribingtocomplications

    Once you have the complication id, you can persist the id in storage for later use.

    You can use Complications.registerComplicationChangeCallback() to subscribe to multiple complication values. All subscriptions are terminated when your app shuts down and must be re-done when your app is launched. When you subscribe, you register a callback to be called when the value updates:

    function onStart(params as Dictionary) as Void {
        // Retrieve persisted Complication ID
        mComplicationId = Storage.getValue(COMPLICATION_ID_KEY);
    
        // Register a callback for receiving
        // updates on complication information
        Complications.registerComplicationChangeCallback(
            self.method(:onComplicationChanged));
    
        // Liking and subscribing
        Complications.subscribeToUpdates(mComplicationId);
    }

    I've opened a bug report here: forums.garmin.com/.../not-possible-to-save-complications-id-to-storage-contrary-to-claim-and-example-in-docs-4-2-0-beta-1-sdk

  • hi mates!

    I did also some progress in gathering data from publishing app through the onBoard menu,

    thanks to  code ^__^

    here is my code, hoping it will help others dev,

    off course all criticisms and improvements are welcome.

    I first tried to store the Id but always returns corrupted data.

    and 3rd party dev app can be launched on copatible devices.

    It has been tested on real Fenix 7 PRO and everything seems to work as expected

  • it seems I can't use the code section