Assistance in using jungle files for Device Qualifiers.

For my watch application, I have separate image resources for round and rectangular watch screens, and they are defined in their own resources folders, but I'm unable to make it work with jungle files.
When I locate the two resource folders ("resources-round" and "resources-rectangle") in

A) the root of the project, the code fails to compile, "Undefined symbol.." with this code:


(new Ui.Bitmap({:rezId=>Rez.Drawables.NavIcon

,:locX=> xOffset

,:locY=> yOffset

})).draw(dc);



B) However, when the folders are located in the "resources" folder under the root of the project, the code compiles, but at run-time the round resources are being displayed on a rectangular watch.


I have made the following entries in the monkey.jungle file:

Round.resourcePath = $(base.resourcePath);resources-round

rectangle.resourcePath = $(base.resourcePath);resourcse-rectangle



But they don't seem to operate.

It seems that the correct approach should be A), but I'm unable to make it work.





(Mac, High Sierra, Eclipse Oxygen, SDK 3.0.3)
  • The vivoactive hr not being recognized as a rectangular device might be indeed a bug though...



    Actually the problem is that the round devices don't seem to be recognised as round in excludeAnnotations. I have had to do all this to exclude rectangle code for the round devices as
    round.excludeAnnotations = rectangle didn't do the trick:
    fenix5.excludeAnnotations = rectangle
    fr645.excludeAnnotations = rectangle
    fr645m.excludeAnnotations = rectangle
    fenix5s.excludeAnnotations = rectangle
    fenix5plus.excludeAnnotations = rectagle
    fenix5splus.excludeAnnotations = rectangle
    fenix5x.excludeAnnotations = rectangle
    fenix5xplus.excludeAnnotations = rectangle
    fenixchronos.excludeAnnotations = rectangle
    round.excludeAnnotations = rectangle
    fr935.excludeAnnotations = rectangle
    vivoactive_hr.excludeAnnotations = round

  • You don't want to just blanket override settings like this...

    fenix5.excludeAnnotations = rectangle


    Doing so strips out the excludeAnnotations from base configurations. i.e., if round.excludeAnnotations had an entry for the fictional flag zebra, the above like would wipe out that exclude for the fenix5. This is typically not what you want.

    If you have resources for round devices in a resources-round folder and resources for rectangular devices in resources-rectangle, you should not need to do any further configuration from the jungle files. I've used the jungles stuff quite a bit in the last week, and I know it works.

    You are the second person this week to mention compile errors for undefined symbols when using the automatic rebuild option. I'm not exactly sure what the best way to handle this in the jungle file, but in my experience the easiest thing to do is to disable the automatic rebuild option and build for a specific device every time.

    Travis
  • I'm patently missing the point here, as I'm not following your response at all.

    You don't want to just blanket override settings like this...
    If you have resources for round devices in a resources-round folder and resources for rectangular devices in resources-rectangle, you should not need to do any further configuration from the jungle files. I've used the jungles stuff quite a bit in the last week, and I know it works.



    It's not just different resources, in my app, round and rectangle devices require differently positioned and named image resources, so I have created layout code for each class
    and call them separately, drawRectResults(dc) needs to be excluded from round compiles and drawRoundResults(dc) needs to be excluded from rectangle compiles.

    I expected
    round.excludeAnnotations = rectangle
    rectangle = round

    to do this, but no, I have had to resort to excluding rectangle from each specific device as I described above.

    (I have tried for 1/2 hr to post my code but the forum rejects with a crazy JSON error!)
  • You don't want to just blanket override settings like this...

    fenix5.excludeAnnotations = rectangle


    Doing so strips out the excludeAnnotations from base configurations. i.e., if round.excludeAnnotations had an entry for the fictional flag zebra, the above like would wipe out that exclude for the fenix5. This is typically not what you want.


    I'm a little curious about this. I looked in the default.jungle file in the Connect IQ SDK and I didn't saw any references to excludeAnnotations. I'm willing to accept that the "real" default.jungle (not the one that's for reference only) could have excludeAnnotations or that it could change in the future, or that you don't want to mess with your own excludeAnnotations (in a base project/folder) by accident.

    However, the programmer's guide has an example of what you said not to do:

    https://developer.garmin.com/connect-iq/programmers-guide/overriding-resources/
    If the app is approaching memory limits, it may be useful to exclude the unused method, especially if the method is sufficiently large and impacts available memory. To do this, set the excludeAnnotations qualifier property in the Jungle file to the appropriate annotation value:
    # Exclude the oldAndBustedAlgorithm() from fenix 5
    fenix5.excludeAnnotations = older


    Another couple of minor nitpicks about the doc:
    - Earlier on, the doc refers to excludedAnnotations (spelled incorrectly)
    - The online version of the doc has references to internal links (with square brackets) which only work in the offline version of the doc distributed with the SDK. Not a big deal, but it looks strange.

    https://developer.garmin.com/connect-iq/programmers-guide/overriding-resources/
    The excludedAnnotations qualifier property allows build instructions to specify specific [annotations][Annotations] that will be excluded when an application is built

    A list of supported localization qualifiers can be found in the [Appendices][] chapter.


    Anyway, what I got from your post is that the correct code would be:
    fenix5.excludeAnnotations = $(fenix5.excludeAnnotations);older


  • RaceQs I was a little curious about this problem, so I made a quick test case:

    monkey.jungle
    project.manifest = manifest.xml
    round.excludeAnnotations = $(round.excludeAnnotations);rectangle
    rectangle.excludeAnnotations = $(rectangle.excludeAnnotations);round


    myApp.mc
    using Toybox.Application;
    using Toybox.WatchUi;
    using Toybox.System;

    (:round) function testAnnotations() {
    System.println("round");
    }

    (:rectangle) function testAnnotations() {
    System.println("rectangle");
    }


    class MyApp extends Application.AppBase {

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


    Seems to work as expected:
    - Round watches print "round"
    - Rectangular watches (including VAHR) print "rectangle"
    - Semiround watches fail with build error (duplicate symbol)
  • Can't edit the above post so I'll add that I also tried multiple exclude annotations for a single "target" and they also worked. e.g. If you want to have 3 sets of code for rectangle, round, and semiround:
    round.excludeAnnotations = $(round.excludeAnnotations);rectangle;semiround
    rectangle.excludeAnnotations = $(rectangle.excludeAnnotations);round;semiround
    semiround.excludeAnnotations = $(semiround.excludeAnnotations);round;rectangle
    Also, looking at your code posted in the VBCMS comments forum as an image, I would suggest skipping the runtime checks for round vs. rectangular and just use two functions with the same name. It's ever so slightly more efficient, but also simpler to read and understand, and slightly more maintainable.

    Instead of:
    https://pastebin.com/NAK0XM6q

    Try:
    https://pastebin.com/EfG36HSP

    That way if you do add support for semi-round devices, you don't have to change redundant code for checking the screen shape..
  • Good pickup on the (missing) doco! I find the whole subject very confusing!
    Anyway, what I got from your post is that the correct code would be:
    fenix5.excludeAnnotations = $(fenix5.excludeAnnotations);older




    But what I'm trying to point out is that a single
    round.excludeAnnotations = rectangle

    doesn't work.
    I don't want to have to create a list of individual ones for each device.

  • I don't want to have to create a list of individual ones for each device.



    My next post after the one you quoted has a test case that hopefully addresses your issue.... (Sorry for the multiple posts. The documentation thing is tangential, as is the "correct" way to add an excludeAnnotation. That post was really aimed at Travis, and it’s too bad the forums don’t support threaded replies.

    The example I posted would also work with "round.excludeAnnotations = rectangle", even if that’s not how you’re supposed to do things.)
  • Yes, threaded replies would be a boon ! (more...)

    [QUOTE=WillNorthYork;n1421610
    I would suggest skipping the runtime checks for round vs. rectangular and just use two functions with the same name. It's ever so slightly more efficient, but also simpler to read and understand, and slightly more maintainable.



    I tried that and it worked in earlier SDK (last year)
    (:round) function drawIcons(dc){
    ...
    }

    (:rectangle) function drawIcons(dc){
    ...
    }

    but the compiler now flags that as an error:
    Duplicate declaration of symbol drawIcons in class DashboardView.
  • The example I posted would also work with "round.excludeAnnotations = rectangle", even if that’s not how you’re supposed to do things.)


    Nope, it doesn't work for me. Please give it a try.