Complications.updateComplication() crashes

I'm seeing crash reports where calls to Complications.updateComplication either causes and exception or crashes with "Symbol Not Found Error".

My app calls this only for devices that support complications and it works on my devices and the sim.

I can't figure out why this is happening quite a bit in the wild. 

I assume that the CIQ store wouldn't allow the app to be installed on a devices that don't have the API level that supports complications.  Is that a correct assumption?

  • fēnix® 7X / tactix® 7 / quatix® 7X Solar / EnduroTm 2: 9.37
    epixTm (Gen 2) / quatix® 7 Sapphire: 8.45
    epixTm (Gen 2) / quatix® 7 Sapphire: 7.48,

    Venu® 2 Plus: 17.04
    fēnix® 7 / quatix® 7: 14.36, 14.68
    epixTm (Gen 2) / quatix® 7 Sapphire: 14.68
    epixTm (Gen 2) / quatix® 7 Sapphire: 14.68
    Forerunner® 255 Music: 17.26
    Venu® 2 Plus: 16.10

    Languages: cht, eng, gre, spa, fre, heb, rus

  • I assume that the CIQ store wouldn't allow the app to be installed on a devices that don't have the API level that supports complications.  Is that a correct assumption?

    Just out of curiosity, why do you assume that? Is it because your app has the ComplicationsSubscriber permission? I feel like your stance is a bit contradicted by:

    My app calls this only for devices that support complications

    That implies that your app may also support devices which don't support complications or that you believe the related guard code (i.e. a has check) may be necessary for whatever reason.

    My educated guess is the store only does gatekeeping based on:
    - the supported devices in manifest.xml
    - the minApiLevel in manifest.xml

    I would be surprised if the store would block an app from being deployed to a device that doesn't support complications due to the presence ComplicationsSubscriber permission (for example), because that would break the legit use case where an app supports both devices which support complications and devices which do not.

  • I thought the store would not let you install an app that was built with an API level that is not compatible with the FW.  No?

  • For devices that don't support complications, all the complications code is excluded.

  • I thought the store would not let you install an app that was built with an API level that is not compatible with the FW.  No?

    You don't "build with an API level", aside from specifying minApiLevel in the manifest (which you have not mentioned). If you're trying to imply that (for example), apps build with CIQ SDK 6.4.2 can only run on devices with API level, that's absolutely not the case. Assuming you build with the most recent SDK available at any given time, the devices that can install your app are determined by:
    - the devices specified in manifest.xml
    - minApiLevel specified in manifest.xml

    For example, if you specify a minApiLevel of 3.3.0, then all devices specified in the manifest which support 3.3.0 (or higher) will be allowed to install your app. Any user with a device with firmware less than 3.3.0 will be prompted to upgrade (if applicable). If a device doesn't support 3.3.0 at all, then they won't see your app. One situation that's come in the past is when an APAC (Asia-Pacific) version of a device only supports much older firmware than the WW (Worldwide) version. This is because APAC devices typically receive updates more slowly than WW devices.

    In this case, if you specify a minApiLevel that's too high, you may end up excluding the APAC version of a device while the WW version is still included. (For some newer devices, the same firmware is used for both APAC and WW.

    For devices that don't support complications, all the complications code is excluded.

    Right so I'm not sure why you would've bothered to do this, given the following assumption:

    "I assume that the CIQ store wouldn't allow the app to be installed on a devices that don't have the API level that supports complications."

    Unless you aren't sure of that assumption.

    You are also implying that you think your code is crashing because the complications code is being run on devices that don't support complications. Even if the above assumption is wrong (which it is, to my understanding), the fact that you exclude complications code in your app for devices which don't support complications (I assume using a has check) should prevent your complications code from running on devices that don't support complications.

    That's what I'm a bit confused about. If you're absolutely sure you prevent complications code from running on devices which don't support complications, then you shouldn't be worried about that as a source of a crash.

  • It’s crashing on devices that are listed as supporting complication as shown above.  My question is why?  To me it looks like it is crashing on devices with older firmware so I think the problem is that I need to do a ‘has’ check.  But that would apply only to the Symbol not found crashes?   What about the exception crashes.  Docs say the only exception throw is if the id isn’t registered.  In that case it would always crash, but it works most of the time.

  • To me it looks like it is crashing on devices with older firmware so I think the problem is that I need to do a ‘has’ check.

    Right so you didn't specify *how* you accomplished this:

    "My app calls this only for devices that support complications"

    I guess you used jungle exclusions as opposed to a has check. I guess I should've inferred that from the fact you said "devices" (it did cross my mind, tbh). But saying a "device supports complications" is fuzzy, as we know it's really the device+firmware combination that's important when it comes to new features.

    Given that 9.37 is quite old for Fenix 7 (the current version is 15.x), I think you might be right.

    I think the problem is that I need to do a ‘has’ check.  But that would apply only to the Symbol not found crashes?  

    You would think so.

    What about the exception crashes.  Docs say the only exception throw is if the id isn’t registered.  In that case it would always crash, but it works most of the time.

    Not sure what's happening there, especially without knowing more about your code.. I know this isn't what you want to hear, but you could always just catch the exception and call it a day.