[TIP] Use excludeAnnotations + jungles to identify devices - no string resources

In the early days of CIQ, one way to identify devices was to define a string resource in each corresponding device resource folder.
So for example in the string resource file of the resources-fenix5 folder, you would have the following:
<strings>
<string id="DeviceName">Fenix 5</string>
</strings>


Today I had some time to replace that implementation with a better approach: jungle and excludeAnnotations.
It is a better approach because the value is compiled into the source and not determined at runtime by loading a string resource.
It improves performance and memory usage.

In a class, duplicate the same property for each corresponding device that you support, and give each one a relevant annotation:
class MyDevice {

(:approachs60)
const DeviceName = "Approach S60";

(:d2charlie)
const DeviceName = "D2 Charlie";

(:descentmk1)
const DeviceName = "Descent Mk1";

(:fenix5)
const DeviceName = "Fenix 5";
}


In your jungle file you just set the list of excludeAnnotations for each device:

approachs60.excludeAnnotations = d2charlie;descentmk1;fenix5
d2charlie.excludeAnnotations = approachs60;descentmk1;fenix5
descentmk1.excludeAnnotations = approachs60;d2charlie;fenix5
fenix5.excludeAnnotations = approachs60;d2charlie;descentmk1
  • This isn't bad if you only want to support a few devices, but the size of the exclusions table grows by one row and one more column for each device you add.

    If you use the string resource, it is just an additional folder with a single file for each device. Of course the string resource technique requires a call to Ui.loadResource(), and probably a function wrapper to make sure you only load it once...

    // never access this directly
    var device_name = null;

    // always use this to get the device name
    function getDeviceName() {
    if (device_name == null) {
    device_name = Ui.loadResource(Rez.Strings.DeviceName);
    }
    return device_name;
    }


    Travis
  • This isn't bad if you only want to support a few devices, but the size of the exclusions table grows by one row and one more column for each device you add.


    My tip is aimed at those looking to improve performance, especially watch faces and widgets where smooth transitioning in the widget loop is crucial.
    Loading the resource, even just once, still comes at a small cost.

    I don't see an extra excludeAnnotations entry and duplicated property per device as that much more effort. ;)
  • Great tip,

    I'm at a point where I only use the exclude annotations to differentiate between "high" and "low" memory devices running CIQ 3.1.

    In the future, I believe this per device structured approach will be useful to stretch compatibility to older devices with different API versions, although per device name might be overkill for my case, maybe broader categories based on CIQ/feature support.

  • Another option is something like this in jungles:

    project.manifest = manifest.xml
    srcBase=source
    resBase=resources
    
    #use breadcrumbs
    base.sourcePath=$(srcBase);source-nomaps
    base.resourcePath=$(resBase)
    
    #use maps
    fenix5x.sourcePath = $(srcBase);source-maps
    fenix5x.resourcePath = $(resBase);resources-maps

    In this case, I use different source based on what's available on the device.  The default is that I draw breadcrumbs, where I then specify devices that have on board maps and use those instead.

    Something similar could be done for low and high memory devices.

  • Thanks for the additional tip jim_m_58,

    Looks useful to manage complexity growth, repeating methods/code for all cases can get out of hand fast I believe. This is a smarter approach to manage large chunks of functionality.

    These examples (with specific use-cases) would complement the programmer's guide resource documentation nicely.




  • There used to be a blog post by about this, but when the developer blogs got changed a while back, I can't find it any more.  

    - any chance of bringing back some of those old blog posts?

    Multi-device support can either be simple or tricky, based on the app itself.  I have some where the same .prg file will run on anything, where with others, jungles or a careful use of "has" is needed.

  • looks like the developer blog got zapped indeed, I probably still have the article somewhere as a draft in my mails, I'll see if i can upload it.

    meanwhile you can use the resources exludes way to do pretty much the same: https://starttorun.info/guestpost-0-tackling-connect-iq-versions-screen-shapes-and-memory-limitations-the-resource-override-version/

  • Bookmarked! 

    What took me a bit of time was understanding the mechanics of the exclude annotations themselves, since they work kind of opposite from the glance annotation, which was the only annotation I used before in Monkey C. I got there through trial and error though.

    PS: I used your "starting to run" tutorial to learn the basics, I really appreciate the work put there for onboarding total noobs into Connect IQ development best practices.