phoneConnected on the vivoactive

I got a vivoactive today, so a real device to test on! It's running FW 2.40.

Tried to load a watchface and a widget I'm working on, and found an interesting thing. Using "phoneConnected" causes the VA to crash.

var settings=Sys.getDeviceSettings();

if(settings.phoneConnected)
{
..
}

(if I change the if to
if(true)
it runs fine)
  • The device firmware doesn't appear to have support for the field you're accessing. Have a look at this post from this morning.

    You can write

    if (settings has :phoneConnected && settings.phoneConnected) {
    // whatever
    }
  • The fact that the firmware doesn't have this support is the problem I'm reporting. I don't want to fill my code with "has" tests! :)

    The layer I'm calling should return true or false in the "unsupported" case, and NOT crash the watch!
  • You are trying to read a variable that doesn't exist. The runtime environment has no option; it does not know that the phoneConnected member exists in a future version of the firmware. All it knows is that the member you are trying to access doesn't exist right now.

    This system of being able to introspect on objects allows Garmin to add features to the SDK without having to keep their code in lock-step with the firmware for each device. It allows developers to write applications that work on devices with older firmware if they so choose. If you don't want to litter your code with :has tests, then don't. You can expect that your application will crash if you leverage a feature that exists in the SDK you built on but does not exist in the firmware that the device is using and users who do not like crashes will post negative reviews on your software.
  • "doesn't exist" is a non sequester, as it DOES exist in the SDK documentation! HAS seems to be an expensive operation, and should only be needed for methods that are DOCUMENTED as only existing on some devices.

    Maybe if the SDK documentation had notes about which methods are available where and when, "HAS" has a place!.

    Again, there is NO reason why calling phoneConnected on a 2.40 vivoactive should crash the watch. I mean CRASH! Garmin logo and rull restart, etc. If the method that passed the compiler doesn't exist in the VM, return null, false, or something!
  • Maybe the connect IQ store needs to be a bit smarter in this case. It knows the .prg, and what it uses (I'd guess), and when someone tries to download something, it also knows the device and it's firmware version.

    Like Google Play, maybe is should be smart enough to say "this (something) is not compatible with your device".
  • "doesn't exist" is a non sequester, as it DOES exist in the SDK documentation!

    It may exist in the documentation *now*, but that feature and the supporting documentation may have been created *after* the firmware running on the device. How do you expect that to be resolved?

    Consider the following code...

    using Toybox.Application as App;
    using Toybox.System as Sys;
    using Toybox.WatchUi as Ui;

    class C
    {
    var i;
    }

    class TestApp extends App.AppBase {

    function initialize() {
    var c = new C();
    if (c.does_not_exist) {
    Sys.println("whoa!");
    }
    }
    }


    How do you expect the system to respond? How is this code any different than the code that you are complaining about.

    HAS seems to be an expensive operation

    The has operator may be expensive, but it is much cheaper than an application that crashes. You only need to call it once and cache the result if you don't like the cost.

    ... should only be needed for methods that are DOCUMENTED as only existing on some devices.

    The documentation mentions specifically that some features are only available for some devices. I don't think it is unreasonable for these things to be documented.

    Maybe if the SDK documentation had notes about which methods are available where and when, "HAS" has a place!.


    The Monkey C Programmers Guide has this to say about the has operator.
    The has operator lets you check if a given object has a symbol, which could be a public method, instance variable, or even a class definition or module. The second argument is the symbol you want to check. It is handy for checking for supported APIs.


    Again, there is NO reason why calling phoneConnected on a 2.40 vivoactive should crash the watch. I mean CRASH! Garmin logo and rull restart, etc. If the method that passed the compiler doesn't exist in the VM, return null, false, or something!

    The Monkey C Programmers Guide has this to say about that...

    Because Monkey C uses dynamic typing, there are many errors for which the compiler cannot check. If the error is of high enough severity, it will raise an fatal API error and cause your app to terminate at runtime. These errors cannot be caught. At this time all of these errors are fatal and there is no way to trap them, though this may be addressed in future updates.
    * Symbol Not Found: A name is being referenced that does not exist in specified object or module.


    The fact that it crashes the device completely is a bug. It seems reasonable to complain about that. Unfortunately for you, that is not what you are complaining about. You have been complaining about the need to check for the existence of a member with the has operator. Your failure to do that, in combination with the undocumented nature of this issue and old firmware have caused the problem. I think it is reasonable to report the problem you've seen (poor docs and crashing the device), but when the day ends, you only control one part of this system... the code you write.
  • The application should NOT load on a device that does not have the methods required. (see Google Play) I started doing embedded VMs about 15 years back (Smalltalk and Java). This is a bug in the system.. HAS is the cheap way out, that will later need to be fixed, and no more. If I have something in the code that it a problem, the byte code compiler should catch it, and then even then when it's loaded to a device, the "loader" (the CIQ app store) should prevent the load on device specific stuff. There is NO excuse for ANY CIQ app to crash a device. None.. But why trust me, as I only started doing systems level code in the 70's! :)

    A clean compile of any CIQ app should NEVER result in the VM causing a reboot of the device. It's that basic and that simple! That's why you use things like OOPS and CIQ!
  • Former Member
    Former Member over 10 years ago
    I have just picked up a vivoactive and started programming for it yesterday, I tried to run one of the sample projects that is SampleRecordView. Has the recording to FIT file been implemented at all? I notice the code is similar to the above and says

    if( Toybox has :ActivityRecording ) ... seems to work on simulator, but when installed on watch, just says "This product doesn't have FIT support".

    Trying to work out if its the watch, the SDK or me.... ?

    Any ideas?

    Also, once on running it, fully crashed the watch too, back to Garmin icon etc same as above.
  • if( Toybox has :ActivityRecording ) ... seems to work on simulator, but when installed on watch, just says "This product doesn't have FIT support".

    I think that this is a pretty good indicator that the device doesn't currently have access to the activity recording module. I can't tell from the documentation if this is intended limitation of the device or it is just something that isn't finished in the firmware's ConnectIQ support. Unless someone digs up some documentation that indicates this is intentional, this question is probably best answered by one of the ConnectIQ team.
  • The application should NOT load on a device that does not have the methods required. (see Google Play)

    You are right in that Google Play does allow developers to prevent installation of apps onto devices that don't have the required features. You are also wrong-- Google Play allows the developer to check for a feature at runtime and respond appropriately. Here is a snippet from the Google Play Device Compatibility page...

    However, if your app's primary functionality does not require a device feature, you should set the required attribute to "false" and check for the device feature at runtime. If the app feature is not available on the current device, gracefully degrade the corresponding app feature. For example, you can query whether a feature is available by calling hasSystemFeature() like this:

    PackageManager pm = getPackageManager();
    if (!pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) {
    // This device does not have a compass, turn off the compass feature
    disableCompassFeature();
    }


    For information about all the filters you can use to control the availability of your app to users through Google Play Store, see the Filters on Google Play document.


    Garmin has implemented this strategy via the has operator.

    I agree that from a user perspective, being prevented from installing an application is preferable to installing the app and finding out that it doesn't work via an error message or an application crash. That isn't currently the way that it works. For the time being, it is up to the developer to ensure that their code does not do something dumb.

    HAS is the cheap way out, that will later need to be fixed, and no more.

    It seems to be working fine for the folks at Google. I'm not sure why it won't be workable for the folks at Garmin.

    There is NO excuse for ANY CIQ app to crash a device. None.. A clean compile of any CIQ app should NEVER result in the VM causing a reboot of the device.

    I don't recall having said anything that could be construed so far as to say that this is acceptable behavior. I don't think anyone here would argue with that point. I do think that it is completely acceptable for your app to crash (just your app, not the entire device) if your code fails to respond correctly to the inputs and environment. Garmin already documents a list of errors that will cause your application to terminate; referencing a symbol that doesn't exist is one of them. Code appropriately.