Symbol lookup best practices?

Most of the time the simulator starts without a problem, but sometimes I get this when I start:

Error: Invalid Value

Details: Failed invoking <symbol>
Stack:
- onUpdate() at C:\Users\Andy\Desktop\Garmin-GIT\Annulus\source\AnnulusView.mc:735 0x10002514

Encountered app crash.
Kill app for run the app
Failed to run the app: Timeout

What's worse it's happening on the watch, after a day or so onUpdate will stop updating when awake, but it does keep updating every minute awake or not. I get something similar in a CIQ_LOG file. I reselect the watch face and it's fine, at least for a while.

Can I fix this by helping the lookup process? I don't have any globals beyond Toybox, so do I use self to say it's a variable or function in the same class? Does a symbol need to be looked up everytime that piece of code is run, or does it remember after the first time? It seems like if it was remembering where it was it wouldn't break the next day.

  • When onUpdate() is called on some devices the dc is cleared before that, so in onUpdate you must always redraw everything you want visible.  If you want the second hand when you are not in low power, you can do that.

  • No, I'm not confused. Yes, probably a poor choice of terms by Garmin.

    	//! This method is called when the device re-enters sleep mode.
    	//! Set the isAwake flag to let onUpdate know it should stop rendering the second hand.
    	public function onEnterSleep() as Void {
    		//reOrb();
    		_isAwake = false;
    		WatchUi.requestUpdate();
    	}
    
    	//! This method is called when the device exits sleep mode.
    	//! Set the isAwake flag to let onUpdate know it should render the second hand.
    	public function onExitSleep() as Void {
    		_isAwake = true;
    		_aWoken = true;
    	}
    

    When you gesture the watch wakes up, shows the second hand for ten seconds, then goes back to sleep. This works like it should. No problems here. Not the same thing as the sleep times in my profile which something else is causing the watchface application to restart at 10pm and 6am. This is when the possibility exists, but not certainty, of the watch face being corrupted.

  • 		// draw the hands face buffer to the screen
    		dc.setColor(Graphics.COLOR_TRANSPARENT, Graphics.COLOR_BLACK);
    		dc.clear();
    		if (self._handsFaceBuffer != null) {
    			dc.drawBitmap(0, 0, self._handsFaceBuffer);
    		}
    
    		if (self._isAwake) {
    			self.reOrbDrawFast(dc);
    /*
    			// debug awake time
    			self._jAwake++;
    			var upTime = jday - self._jStart;
    			var awakeDay = self._jAwake / upTime;
    			var jt = Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER;
    			dc.setColor(Graphics.COLOR_GREEN, Graphics.COLOR_TRANSPARENT);
    			dc.drawText(40, self._Ymax * 0.8, Graphics.FONT_SYSTEM_TINY, upTime.format("%5.2f"), jt);
    			dc.drawText(40, self._Ymax * 1.0, Graphics.FONT_SYSTEM_TINY, awakeDay.format("%5i"), jt);
    			dc.drawText(40, self._Ymax * 1.2, Graphics.FONT_SYSTEM_TINY, self._batteryRate.format("%5.1f"), jt);
    */
    		}
    

    Every pass of onUpdate the bitmap is drawn. If isAwake is true, then draw second hand and some other polygons. What's happening when the application is restarted is I'm getting something that isn't this code.

  • Ok, an important thing here is is sounds like you have a watch with an AMOLED display.

    On those, there is a basic setting for "Always on Display".  (System->Display>General Use on devices I've seen) Make sure that is what you have set.  Otherwise when you drop to low power, the screen will blank after the timeout specified.

    Devices with MIP displays don't blank the screen

  • Yes, and that's why I keep saying that each time onUpdate is called, you have to redraw everything you expect to see..

  • you probably have sleep hours 10pm-6am

    Do you have in app something like:

    function getServiceDelegate()

    {
    return [ new _ServiceDelegate() ];

    }

    and class


    class _ServiceDelegate extends System.ServiceDelegate

    {
    function initialize() {
    System.ServiceDelegate.initialize();

    }

    //....

    }

  • Yes, that's what I do. So when there is stuff on the screen I didn't draw or I clear and it doesn't go away, then that's when there is a problem.

  • This is all there is to the service delegate. It's all that comes with the Analog face in the SDK. I haven't done anything with it.

    //! Receives watch face events
    class AnnulusDelegate extends WatchUi.WatchFaceDelegate {
    	private var _view as AnnulusView;
    
    	//! Constructor
    	//! @param view The analog view
    	public function initialize(view as AnnulusView) {
    		WatchFaceDelegate.initialize();
    		_view = view;
    	}
    
    	//! The onPowerBudgetExceeded callback is called by the system if the
    	//! onPartialUpdate method exceeds the allowed power budget. If this occurs,
    	//! the system will stop invoking onPartialUpdate each second, so we notify the
    	//! view here to let the rendering methods know they should not be rendering a
    	//! second hand.
    	//! @param powerInfo Information about the power budget
    	public function onPowerBudgetExceeded(powerInfo as WatchFacePowerInfo) as Void {
    		System.println("Average execution time: " + powerInfo.executionTimeAverage);
    		System.println("Allowed execution time: " + powerInfo.executionTimeLimit);
    		_view.turnPartialUpdatesOff();
    	}
    }
    

  • it's not service delegate....

    so it looks your watch face base on analog sample, so build it, install and check if it runs well

    if yes problem is in code you have added

    if no, it's problem in sample, firmware, etc.