Complications questions

hi mates,

I think I am not "smart" enough or lack of skill to understand the complications,

I read the CoreTopic again and again but in vain ;)

So far I did test that:

function onPress(clickEvent){
		var c = clickEvent.getCoordinates();
		if(c[0]>gW*0.4&&c[0]<gW*0.6&&c[1]>gW*0.4&&c[1]<gW*0.6){
				Sys.println("ok");
    			var K = new Complications.Id(Complications.COMPLICATION_TYPE_SUNSET);

				if(K!=null){
					Sys.println(Complications.getComplication(K).value);
					try{
            			Complications.exitTo(K);Sys.println("exitTo OK");
						return true;
					} catch ( e ) {Sys.println("AppNotInstalled");}
				}
		}
	}

it seems to work, I mean I have the value and the "exitTo OK"

I guess the similator does not simulate the app opening right?

That is the only code block which contains Complications code.

So now my question is, what is the interrest of "suscribe" etc?

have a great day

  • Native code, CIQ device apps and audio providers publish data of interest as complications, and watch faces consume that data by subscribing to complications. The point of subscribing is to display the data on the watch face and to allow the user to open the app by long pressing the displayed complication.

    Here's an example of a watch face that subscribes to the native heart rate complication.

    1) Use 4.2.0 beta1 SDK

    2) Create new watch face app (without settings) named "ComplicationFace"

    3a) Replace resources/layout/layout.xml with:

    <layout id="WatchFace">
        <label id="HeartRateLabel" x="center" y="center" font="Graphics.FONT_LARGE" justification="Graphics.TEXT_JUSTIFY_CENTER" color="Graphics.COLOR_BLUE" />
    </layout>

    3b) Replace source/ComplicationFaceApp.mc with:

    import Toybox.Application;
    import Toybox.Lang;
    import Toybox.WatchUi;
    import Toybox.Complications;
    
    class ComplicationFaceApp extends Application.AppBase {
        function initialize() {
            AppBase.initialize();
        }
    
        var heartRateComplicationId;
        function onStart(state as Dictionary?) as Void {
            heartRateComplicationId = new Complications.Id(Complications.COMPLICATION_TYPE_HEART_RATE);
            Complications.registerComplicationChangeCallback(self.method(:onComplicationChanged));
            Complications.subscribeToUpdates(heartRateComplicationId);
        }
    
        function onComplicationChanged(complicationId as Complications.Id) {
            if (complicationFaceView != null && complicationId == heartRateComplicationId) {
                try {
                    var complication = Complications.getComplication(complicationId);
                    complicationFaceView.updateHeartRate(complication.value);
                } catch (e) {
    
                }
            }
        }
    
        var complicationFaceView;
        function getInitialView() as Array<Views or InputDelegates>? {
            complicationFaceView = new ComplicationFaceView();
            return [ complicationFaceView ] as Array<Views or InputDelegates>;
        }
    }
    
    function getApp() as ComplicationFaceApp {
        return Application.getApp() as ComplicationFaceApp;
    }

    3c) Replace source/ComplicationFaceView.mc with:

    import Toybox.Graphics;
    import Toybox.Lang;
    import Toybox.System;
    import Toybox.WatchUi;
    
    class ComplicationFaceView extends WatchUi.WatchFace {
        function initialize() {
            WatchFace.initialize();
        }
    
        function onLayout(dc as Dc) as Void {
            setLayout(Rez.Layouts.WatchFace(dc));
        }
    
        var heartRate = null;
    
        function onUpdate(dc as Dc) as Void {
            var view = View.findDrawableById("HeartRateLabel") as Text;
            if (heartRate != null) {
                view.setText("" + heartRate);
            }
            View.onUpdate(dc);
        }
    
        function updateHeartRate(updatedHeartRate) {
            heartRate = updatedHeartRate;
        }
    }

    If you run this in the sim, you will see the continuously-updated HR value displayed in the center of the watchface.

    One of my questions around this feature is exactly how useful it is for device apps. Since device apps don't run in the background while you're looking at a watch face (as far as I know), it seems that you'll only get the data from the last time the app was active, which might not be useful in all cases. (Unless I'm missing something here.)

  • With a "normal" device app, the background will run if the main app itself or another CIQ device app isn't running.  Then you add in super apps, which are really device apps with a glance view on 4.x devices,.  To me, it makes sense that both could be publishers.

    the background service part looks to be the important part to me.

  • So data will be updated every 5 minutes.

    So it can't be any frequent change data like HR and a lot of additional code end checking nulls.

    So advantage from complication are

    - other WF can use data from apps if it will be public

    - I can use more memory dividing code between WF and publishers but will have to ask user to install publisher (and update parallel) - but if I have enough memory I can put my code into app's background

    - I can exitTo system/dev app but not on not touched device

  • I'm pretty sure complications will only be available on touch devices.  The current generation are usually touch or touch+button - the v2, v2+, 955, f7, epix2.  In CIQ, HR might not be a great example here, as any watch face can get that pretty easily.  But there are metrics that aren't exposed in CIQ where this would be useful.

    Consider the case where I have a glance/widget that gets info from the net every 10 minutes.  I can publish that complication and your WF can display it, where  you don't have to implement the code needed actually get the data from the web.

  • So data will be updated every 5 minutes.

    If it makes you feel better, the limit for Apple Watch complication updates is 4 times per hour:

    https://developer.apple.com/documentation/clockkit/keeping_your_complications_up_to_date

    I agree it seems too slow for some use cases.

  • yes, but as I have described user has to install publisher.

    And publisher is an app so it takes app slot.

    I don't want to think how watch will run if 5 publishers every 5 minutes will call webrequest.

    There is Toybox.WatchUi.Selectable from 2.1 so it's possible to add to not touched device delegate. 

  • Apple is full of limits (e.g. widgets) and than it run so good :-)

  • Apple is full of limits (e.g. widgets) and than it run so good :-)

    Yeah.

    The way Apple complications work is that only complications on the current watch face will be updated.

    Garmin is full of limits too, but I guess the difference is there are more perceived problems? I know some people who feel like Garmin is simple and good at what it does. I don't know if anyone is blown away by the user experience.

  • The user only need install the CIQ publisher they want to use.  But if they have something installed that publishers, they can get that data in any WF that supports complications without installing anything new..

  • on condition complication is public...

    can one app publish more than one complication?

    can complication return something more complicate like dictionary?