Don't load the bitmap after the transfer on my watch.

Hello everybody,

I try (because it's fun) to develop my first watchface. Unfortunately, all the topics, help and tutorials are in English so it's quite complicated following the bug I could have ...

After some days, I finalized an watchface working on ConnectIQ, but after transferred the app on my Forerunner 245, I found a mistake. It seems that the bitmap is not loaded and each time I change what I want to see (go to a menu, an app or whatever) then come back to the clock screen, the last screen stay in font. I don't really understand what it happens. Do you have an idea ?

Thank's for your help.

My code : 

using Toybox.WatchUi as Ui;
using Toybox.Graphics as Gfx;
using Toybox.System as Sys;
using Toybox.Lang as Lang;
using Toybox.Application as App;
using Toybox.Time.Gregorian as Date;
using Toybox.ActivityMonitor as Act;
using Toybox.Activity as Acty;

class WFView extends Ui.WatchFace {
    var myBitmap;

    function initialize() {
        WatchFace.initialize();
        myBitmap = Ui.loadResource(Rez.Drawables.fondWF); 
    }

    function onLayout(dc) {
        dc.clear();
        setLayout(Rez.Layouts.WatchFace(dc));
    }

    function onShow() {
    }

    function onUpdate(dc) {
        dc.clear(); 
        View.onUpdate(dc);
        dc.drawBitmap(0, 0, myBitmap); 

        // Function ClockDisplay
        var clockTime = Sys.getClockTime();
        var timeStringHour = Lang.format("$1$", [clockTime.hour]);
        var timeStringMin = Lang.format("$1$", [clockTime.min.format("%02d")]);

        dc.setColor(Graphics.COLOR_BLUE, Graphics.COLOR_TRANSPARENT);
        dc.drawText(120, 20, Gfx.FONT_SYSTEM_NUMBER_HOT, timeStringHour, Graphics.TEXT_JUSTIFY_CENTER );
        dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
        dc.drawText(120, 130, Gfx.FONT_SYSTEM_NUMBER_HOT, timeStringMin, Graphics.TEXT_JUSTIFY_CENTER ); 

        // Function DateDisplay
        var now = Time.now();
        var date = Date.info(now, Time.FORMAT_LONG);
        var dateString = Lang.format("$1$ $2$", [date.day, date.month]);
        var dayString = Lang.format("$1$", [date.day_of_week]);

        dc.setColor(Graphics.COLOR_DK_GRAY, Graphics.COLOR_TRANSPARENT);
        dc.drawText(120, 0, Gfx.FONT_XTINY, dateString, Gfx.TEXT_JUSTIFY_CENTER );
        dc.setColor(Graphics.COLOR_DK_GRAY, Graphics.COLOR_TRANSPARENT);
        dc.drawText(120, 15, Gfx.FONT_XTINY, dayString, Gfx.TEXT_JUSTIFY_CENTER );
        
    // continued ...

// ... continued
       // Function BatteryDisplay 
        var batteryinfo = Sys.getSystemStats().battery;
        var stats = Sys.getSystemStats();
        var pwr = stats.battery;
        var battery = Lang.format("$1$%",[pwr.format("%2d")]);
        dc.setColor(Graphics.COLOR_DK_GRAY, Graphics.COLOR_TRANSPARENT);
        dc.drawText(120, 220, Gfx.FONT_XTINY, battery, Gfx.TEXT_JUSTIFY_CENTER );

        // Function StepCountDisplay 
        var stepCount = Act.getInfo().steps.toString(); 

        dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
        dc.drawText(40, 100, Gfx.FONT_XTINY, stepCount, Gfx.TEXT_JUSTIFY_CENTER ); 
        dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
        dc.drawText(40, 120, Gfx.FONT_XTINY, "Step", Gfx.TEXT_JUSTIFY_CENTER ); 

 // continued ...

// ... continued

       // Function HeartrateDisplay
        var heartRate = Activity.getActivityInfo().currentHeartRate;
        if(heartRate==null) {
            var HRH=Act.getHeartRateHistory(1, true);
            var HRS=HRH.next();
            if(HRS!=null && HRS.heartRate!= Act.INVALID_HR_SAMPLE){
                heartRate = HRS.heartRate;
            }
        }
        if(heartRate!=null) {
            heartRate = heartRate.toString();
        }
        else{
            heartRate = "--";
        }

        dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
        dc.drawText(200, 100, Gfx.FONT_XTINY, heartRate, Gfx.TEXT_JUSTIFY_CENTER ); 
        dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
        dc.drawText(200, 120, Gfx.FONT_XTINY, "Bpm", Gfx.TEXT_JUSTIFY_CENTER ); 
    }
}

  • It seems that the bitmap is not loaded and each time I change what I want to see (go to a menu, an app or whatever) then come back to the clock screen, the last screen stay in font.

    I don't understand the problem you're trying to describe. Are you saying that if you have your watch face active and you go into a menu (by holding the menu key) and then exit the menu (by pressing back) your watch face doesn't display? What is displayed instead? It might be easier to show a video of what you are seeing instead of trying to describe it.

    Just looking at your code, I don't really see anything wrong with it, but I do see some unusual stuff. Here is a snip of your original code with irrelevant bits removed...

    class WFView extends Ui.WatchFace {
        var myBitmap;
    
        function initialize() {
            WatchFace.initialize();
            myBitmap = Ui.loadResource(Rez.Drawables.fondWF); 
        }
    
        function onLayout(dc) {
            dc.clear();
            setLayout(Rez.Layouts.WatchFace(dc));
        }
    
        function onShow() {
        }
    
        function onUpdate(dc) {
            dc.clear(); 
            View.onUpdate(dc);
            dc.drawBitmap(0, 0, myBitmap); 
        }
    }

    Here is how I think I would write it.

    class WFView extends Ui.WatchFace {
        var myBitmap;
    
        function initialize() {
            WatchFace.initialize();
        }
    
        function onLayout(dc) {
            // this is not necessary and should be removed
            // dc.clear();
    
            // if you are not drawing anything with the layout, you should
            // remove the xml for the layout definition and remove this line
            // setLayout(Rez.Layouts.WatchFace(dc));
            
            // this was moved here from initialize. it shouldn't be necessary
            // to do it here, but it is ideal to delay loading resources until now
            myBitmap = Ui.loadResource(Rez.Drawables.fondWF);
        }
    
        // this should be removed if you aren't going to do anything in it
        // function onShow() {
        // }
    
        function onUpdate(dc) {
        
            // if you are using a layout, then use this code
            // vvv
            // View.onUpdate(dc);
            // dc.drawBitmap(0, 0, myBitmap);         
            // ^^^
            
            
            // if your layout isn't doing anything use this code
            // vvv
            dc.setColor(Gfx.COLOR_BLACK, Gfx.COLOR_BLACK);
            dc.clear(); 
            dc.drawBitmap(0, 0, myBitmap); 
            // ^^^
            
            // the rest of your drawing stuff from above
        }
    }

    Also, just a minor style thing... you seem to use 'Graphics' in some places and 'Gfx' in others. You should probably pick one, update the using statement as appropriate, and then make your code consistent.

  • Hi Travis,

    Thank you for your reply. I make the modification according to your comments.

    But as you said, it doesn't change how the watchface work. So the link below is the video to what happen.

    drive.google.com/.../view

  • I've requested access to view your image. Will look at it as soon as I get permission.

  • So I watched the video you provided, and it looks like you are viewing the watch face from within the watch face selection menu. If you actually select the watch face and return to the watch face screen do you see the problem?

    What does the start of your onUpdate() method look like now?

  • Yes, if I select the watchface then come back to the "normal" view, I find the same problem ... the background is the last shown instead of the background normally loaded (fond.png).

    I took this video like this just because it was more simple.

    The onUpdate() code :

    function onUpdate(dc) {

        dc.setColor(Gfx.COLOR_BLACK, Gfx.COLOR_BLACK);
        dc.clear();
        dc.drawBitmap(0, 0, myBitmap);

    // Function ClockDisplay
        var clockTime = Sys.getClockTime();
        var timeStringHour = Lang.format("$1$", [clockTime.hour]);
        var timeStringMin = Lang.format("$1$", [clockTime.min.format("%02d")]);

        dc.setColor(Gfx.COLOR_BLUE, Gfx.COLOR_TRANSPARENT);
        dc.drawText(120, 20, Gfx.FONT_SYSTEM_NUMBER_HOT, timeStringHour, Gfx.TEXT_JUSTIFY_CENTER );
        dc.setColor(Graphics.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
        dc.drawText(120, 130, Gfx.FONT_SYSTEM_NUMBER_HOT, timeStringMin, Gfx.TEXT_JUSTIFY_CENTER );

    // Function DateDisplay
        var now = Time.now();
        var date = Date.info(now, Time.FORMAT_LONG);
        var dateString = Lang.format("$1$ $2$", [date.day, date.month]);
        var dayString = Lang.format("$1$", [date.day_of_week]);

        dc.setColor(Gfx.COLOR_DK_GRAY, Gfx.COLOR_TRANSPARENT);
        dc.drawText(120, 0, Gfx.FONT_XTINY, dateString, Gfx.TEXT_JUSTIFY_CENTER );
        dc.setColor(Gfx.COLOR_DK_GRAY, Gfx.COLOR_TRANSPARENT);
        dc.drawText(120, 15, Gfx.FONT_XTINY, dayString, Gfx.TEXT_JUSTIFY_CENTER );

    // Function BatteryDisplay
        var batteryinfo = Sys.getSystemStats().battery;
        var stats = Sys.getSystemStats();
        var pwr = stats.battery;
        var battery = Lang.format("$1$%",[pwr.format("%2d")]);
        dc.setColor(Gfx.COLOR_DK_GRAY, Gfx.COLOR_TRANSPARENT);
        dc.drawText(120, 220, Gfx.FONT_XTINY, battery, Gfx.TEXT_JUSTIFY_CENTER );

    // Function StepCountDisplay
        var stepCount = Act.getInfo().steps.toString();

        dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
        dc.drawText(40, 100, Gfx.FONT_XTINY, stepCount, Gfx.TEXT_JUSTIFY_CENTER );
        dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
        dc.drawText(40, 120, Gfx.FONT_XTINY, "Step", Gfx.TEXT_JUSTIFY_CENTER );

    // Function HeartrateDisplay
        var heartRate = Activity.getActivityInfo().currentHeartRate;
        if(heartRate==null) {
            var HRH=Act.getHeartRateHistory(1, true);
            var HRS=HRH.next();
            if(HRS!=null && HRS.heartRate!= Act.INVALID_HR_SAMPLE){
                heartRate = HRS.heartRate;
            }
        }
        if(heartRate!=null) {
            heartRate = heartRate.toString();
        }
        else{
            heartRate = "--";
        }
        dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
        dc.drawText(200, 100, Gfx.FONT_XTINY, heartRate, Gfx.TEXT_JUSTIFY_CENTER );
        dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
        dc.drawText(200, 120, Gfx.FONT_XTINY, "Bpm", Gfx.TEXT_JUSTIFY_CENTER );
    }
    }

  • I'll have to test this on a device when I get some time.

  • Thank you for your help. I wait your feedback and hope you will find the problem.

  • I cannot reproduce a problem on my fr245m w/5.12 firmware. I don't have the exact same device (fr245 vs fr245m), but with respect to graphics and the UI system, the music and non-music variants are the same.

    IMG_1140.mov
    IMG_1141.mov

    Here is the .PRG that I've built using the 3.2.2 SDK.

    ForumsWatchFace.prg

  • I asked a colleague verify on a fr245. That device had 5.05 firmware and had no problem with that same .PRG.