Filter devices based on must have feature

I'm still a little unsure on how to approach if I want to write a watchface for devices that MUST have a desired feature.

In my case I want to only support devices that do support following:

  • Vector Font which means API level must be 4.2.1 or higher
  • OnDeviceSettings which means API level must be 2.4.0 or higher

When I now want to determine which devices do support those features by 100% (no matter if they have outdated firmwares or if they are asian or european based) how do I continue now? If my watchface can be installed I must be sure that it supports the features I need.

I think I must find out which devices have been released with API level 4.2.1 or higher on their first release, correct? Can I just say, that the most restricting feature are the vector fonts so I just check which devices do support vector fonts and check  the list of supported devices there:

https://developer.garmin.com/connect-iq/api-docs/Toybox/Graphics/VectorFont.html

I can simply use the list of supported devices from the vector font supported devices list, but how do I continue now? Is that all or must I somehow make sure that even the first version of a device was already supporting vector font by making sure, that the watch was released with API 4.2.1 or higher?

My goal is that my watchface can only be installed on devices with API 4.2.1 or higher that do support vector fonts for sure (so I do not need to check for vector font support via :has)

Question:

  • is checking the supported devices list of a feature enough for my use case?
  • is this logic true for any feature?

Top Replies

  • store will make sure that device has the firmware / CIQ specified for a given part number

    This is all I needed to know. I don't care if there may exist devices that can't install my watchface…

All Replies

  • Ok, in the case of vector fonts, first thing is the minimum api level.  The result will be devices that "may" have vector fonts.

    Then, look at supported devices for getVectorFont.  For example, both the venu3 and va5 have CIQ 5, but the va5 doesn't have vector fonts.

    Then you need to consider which vector fonts are available on a specific device.  Not all devices have the same fonts,

    The sim seems pretty good at showing what will work and what won't with this.

  • Then, look at supported devices for getVectorFont

    The same devices as if I look at the VectorFont class, so this should be the same I guess.

    Then you need to consider which vector fonts are available on a specific device.

    I'm aware of that, that's fine as long as one is available. I do define the font name in a device specific class and use it.


    But after all, is using the minApiLevel in the manifest.xml not enough to ensure that my watchface can only be installed on devices that do support VectorFonts if I set the level to 4.2.1?

  • Earlier in this case I would've used a filter for min API level 4.2.1, but a few months ago I changed my tactic. Now what I do is to check if the device has some function related to this feature. The reason is that even if the api docs tells you this feature was added to api 4.2.1 it still can be only for a select set of devices. So in your case I would look for getSettingsView and for getVectorFont.

    I have a script that does generate the monkey.jungle for me based on these (and other) criteria, but the idea behing checking the capability of a device is this:

    Search for the string "<functionName>" (including the 2 double quotes!) in the SDK/Devices/<device>/<device>.api.debug.xml file. If it's there the device has the function, if not then it doesn't have it.

  • I have a script (program in my case) that does a bunch of things as well so that is just a small extension for me. If I do it like you suggest and I find a function (or class) inside the xml file, can I then be sure that ALL possible firmwares for this device do have the function?

  • If I do it like you suggest and I find a function (or class) inside the xml file, can I then be sure that ALL possible firmwares for this device do have the function?

    No, you can't.

    TL;DR: if you want to be absolutely sure that users cannot install your app unless they have support for a given feature that's only present for a certain minimum API level (but not for ALL devices with that min API level), then you have to do two things:

    - set a minimum API level in your manifest (minSdkVersion)

    - manually select devices to support, based on your knowledge that they have the feature you want

    There's a situation which used to be very common in the past, where Asia-Pacific variants of devices would not get the latest firmware / CIQ at the same time as the world wide variants. This is less common now, as many newer devices do not have separate WW and APAC variants, but it still exists (and there's other scenarios - see below). This situation is where setting a min API level is useful for preventing users from installing your app when they don't have the requisite CIQ.

    How do you figure out which API level(s) will be present for a given device?

    What you can do is for each device in question, check compiler.json under the devices library to see the minimum CIQ version for each part number.

    In Windows, the devices library is at %APPDATA%\Garmin\ConnectIQ\Devices. Under this folder, each subfolder is named after a CIQ device id (e.g. Devices\fenix7x).

    For example, fenix7x > compiler.json > partNumbers[] is an array of part number info. Each element has the following fields of interest: connectIQVersion, firmwareVersion, number (part number - *not* the same as the part number on the box).

    e.g. fenix7x > compiler.json > partNumbers[0]

    "connectIQVersion": "5.0.0",
    "firmwareVersion": 1622,
    "number": "006-B3907-00"

    e.g. fenix7x > compiler.json > partNumbers[3]

    "connectIQVersion": "4.2.3",
    "firmwareVersion": 1431,
    "number": "006-B4341-00"

    Also of interest is the worldWidePartNumber field at the top-level.

    e.g. fenix7x > compiler.json > worldWidePartNumber

    "worldWidePartNumber": "006-B3907-00"

    What does this all mean?

    For a given part number, connectIQVersion / firmwareVersion refer to the minimum firmware / CIQ version combo that will be required for users to install your app on that device. In this case, some fenix7x devices will have 5.0.0, but others will have 4.2.3.

    The part number corresponding to worldWidePartNumber is the default / worldwide version of the device. The other part numbers may be APAC (Asia-Pacific devices) or they may even correspond to some other variant with a different model name (but it's equivalent as far as CIQ is concerned.) For example, Enduro 2 (006-B4341-00) is simply another part number of fenix7x as far as CIQ is concerned (*).

    So in this case, the "main" variant of fenix7x is guaranteed to have CIQ 5.0.0 (as far as your app is concerned), but the Enduro 2 variant is only guaranteed to have CIQ 4.2.3. Supposing your app needs CIQ 5.0.0 at minimum. since Enduro 2 is just another part number under the CIQ fenix7x device type, you have no way of excluding Enduro 2 (or guaranteeing 5.0.0) except by setting minSdkVersion in manifest.xml to 5.0.0.

    You can usually guess if a part number corresponds to an APAC version as follows:

    - the device in question has more than one part number

    - the part number in question is not the worldWidePartNumber

    - the part number in question contains APAC languages / font sets (as per compiler.json). (Note that with newer devices, the main part number may also contain APAC languages / font sets.

    It's been the case forever that APAC devices are slow to get updates compared to WW devices. In some cases, APAC devices *never* receive the latest firmware / CIQ version that the WW version gets.

    (*) How did I know that? I looked at the JSON returned by [https://apps.garmin.com/api/appsLibraryExternalServices/api/asw/deviceTypes], which is queried whenever you click on the devices tab for an app in the CIQ store

    From that response, I can also see that "006-B2396-00" is the APAC version of FR235.

    e.g. of deviceTypes JSON

    [
    ...
        {
            "id": "21",
            "partNumber": "006-B2396-00",
            "name": "Forerunner® 235",
            "additionalNames": [],
            "imageUrl": "https://static.garmincdn.com/en/products/010-03717-54/g/cf-sm.jpg",
            "urlName": "forerunner235-apac"
        }
        ...
        {
            "id": "261",
            "partNumber": "006-B4341-00",
            "name": "EnduroTm 2",
            "additionalNames": [],
            "imageUrl": "https://res.cloudinary.com/it-production/image/upload/v1648824135/Product_Images/en/products/010-02754-00/g/pd-05-sm-66796f25-e282-4a31-bd44-93fb6ddbf2ee.jpg",
            "urlName": "enduro2"
        },
        ...
    ]

    So how does all of this work with minSdkVersion in manifest.xml?

    When you export your project to an IQ file for release, the compiler builds a PRG of your app for each part number of each device that you've specified in manifest.xml. If any of the part numbers has a connectIQVersion (in compiler.json) which is lower than minSdkVersion, that part number will be skipped during the export process (you'll get a warning).

    That's why ppl who set minSdkVersion to something higher than 1.0.0 or 1.2.0 often get warnings for APAC part numbers because they're skipped during the export process.

    It goes without saying that if a user tries to install your app and they don't have the minimum API version / firmware that was present in the device file at export time (and saved in the export manifest in the .IQ file), the store will tell them they have to upgrade their firmware before they can install the app.

  • So in this case, the "main" variant of fenix7x is guaranteed to have CIQ 5.0.0

    Not exactly. It means that the latest firmware version for those devices has CIQ 5.0.0, IF THE USER UPGRADED THE FW!. If not, then they'll have some older FW. Now this is not a problem in case you have minApiLevel set to 5.0.0 in your manifest, because then GC, GE will not let the user to install your app unless they upgrade the FW. But if your manifest has some lower minApiLevel then it won't work. 

  • So in this case, the "main" variant of fenix7x is guaranteed to have CIQ 5.0.0

    Not exactly. It means that the latest firmware version for those devices has CIQ 5.0.0, IF THE USER UPGRADED THE FW!.

    Why did you cut off my quote and remove crucial context?

    So in this case, the "main" variant of fenix7x is guaranteed to have CIQ 5.0.0 (as far as your app is concerned)

    AS FAR AS YOUR APP IS CONCERNED

    The export process saves the following information in its manifest:

    - from manifest.xml: minSdkVersion

    - from each part number for each supported device: connectIQVersion, firmwareVersion

    As I said, if a user tries to download your app for a part number that has a lower connectIQVersion / firmwareVersion than specified in the export manifest, then the store will block the download and ask the user to upgrade their firmware, REGARDLESS of minSdkVersion. Afaik, minSdkVersion only serves to weed out incompatible part numbers at export time (ofc after it's done so, it becomes redundant except for informative purposes.)

    This has been discussed in the forums previously, and I think you were part of the discussions.

  • If you want to validate what I said, try hacking an IQ manifest file a device file to set a fictitious too-high CIQ version for a given part number (that you own), leave minSdkVersion at 1.0.0, and upload that IQ as a beta app. (You may have to manually re-sign the manifest file tho.)

    You should be blocked from installing the app, regardless of the low minSdkVersion.

    EDIT: ofc a far easier way to do this test is to hack the device file before you build the IQ file (derp)

    I think someone already validated what I said (their device may not have had the real CIQ version specified in the latest device files, at the time.)

    Either way, you can easily do this test if you doubt that it works as described.

  • the "main" variant of fenix7x is guaranteed to have CIQ 5.0.0

    It is true if your app is installed on a specific device, but not, when a user that has this type of device is trying to install it, because then it depends on their FW version, so instead of being able to install it they might get a warning that asks them to upgrade the firmware.

    I also had users asking me to send them specially built versions (built with SDK 6) because there are bugs in epix (I think) that prevent them from upgrading, and then they can't install anything compiled with SDK 7.

  • It is true if your app is installed on a specific device, but not, when a user that has this type of device is trying to install it, because then it depends on their FW version, so instead of being able to install it they might get a warning that asks them to upgrade the firmware.

    Uh is that not what I said above? It's more than a warning, you are prevented from installing the app (as you added in your edit) unless you have, at a minimum, the CIQ / firmware version combo specified in the manifest.

    So I will reiterate,

    AS FAR AS YOUR APP IS CONCERNED,

    the connectIQVersion / firmwareVersion specified for a given device / part number in compiler.json are the minimum guaranteed versions.

    In other words, I'll assume the following quote is incorrect (AS FAR AS YOUR APP IS CONCERNED), unless proven otherwise:

    Not exactly. It means that the latest firmware version for those devices has CIQ 5.0.0, IF THE USER UPGRADED THE FW!. If not, then they'll have some older FW.

    Just to explain myself fully, if a given release of your app cannot be installed on a device which does not have the requisite CIQ / firmware combo at a minimum, then AS FAR AS YOUR APP IS CONCERNED, every device on which the release is installed is guaranteed have the requisite CIQ / firmware combo (at a minimum).

    Real-world analogy:

    - Given: an amusement park ride has a sign that says "you must be at least this (*) tall to ride" (* 5 feet / 1.524 metres)

    - Conclusion: everyone who gets on the ride is GUARANTEED to be at least 5 feet / 1.524 metres

    This doesn't preclude the existence of shorter people who want to get on the ride, it just means those people aren't allowed to get on the ride. As far as the ride's designers and operators are concerned, they don't count. For example, given the constraint above, the ride's designer and amusement park management don't have to worry about whether the ride is safe for people who are shorter than 5' tall.

    Similarly, given that "main" part number's info in compiler.json for fenix7x specifies CIQ 5.0.0, any app developer using the latest device files doesn't have to worry about devices with that part number which have anything less than CIQ 5.0.0, because the store won't let the user install the app in that case. AS FAR AS THE APP IS CONCERNED, that part number will have at least CIQ 5.0.0.

    EDIT: Also note that OP said (emphasis mine):

    My goal is that my watchface can only be installed on devices with API 4.2.1 or higher that do support vector fonts for sure (so I do not need to check for vector font support via :has)

    So it's relevant to point out a situation where the store will prevent an app from being installed, based on information in compiler.json.

    It is true if your app is installed on a specific device, but not, when a user that has this type of device is trying to install it, because then it depends on their FW version, so instead of being able to install it they might get a warning that asks them to upgrade the firmware.

    I don't think anyone said that compiler.json can magically force all devices to have the firmware / CIQ specified for a given part number. I never said that explicitly or implicitly.

    Clearly it would be impossible for the firmware / CIQ versions in compiler.json to always match the actual versions "in the wild" except possibly for the initial release of a device. I don't think any reasonable person would argue otherwise.

    What I DID say was that the store will make sure that device has the firmware / CIQ specified for a given part number, otherwise the user won't be able to install the app.