FIT gets automatically saved and can't be removed before launching it as intent

Hey all,

couldn't find a similiar question for this topic so I was hoping you could help me out here.

In my app I'm downloading FIT files from an API through Communications.makeWebRequest and after investigating I noticed that the files (if the request was successfull of course) are immediately stored in the flash.

At first I thought that it's not big deal since I have the reference through the iterator returned from the callback so I could just do:

def callback(code, data) {
    if (code == 200) {
    var course = data.next();
    var intent = course.toIntent();
    course.remove();
    System.exitTo(intent);
    }
}


The problem is that the data of the course has vanished at this point so while the device proposes you to choose from an activity for this intent and you can launch that activity, there will be no waypoints to navigate to.

So the only way to guarantee that the navigation works is leaving the file stored in the flash which is probably not what a user expects nor wants though.

Is there anyone working with FIT files aswell and found a workaround or has an advice for me?

Thanks in advance!

  • When you download a workout or a course, that is stored on the watch and is available through both your app and via the native controls on the watch. You can delete these once you are done, but can only delete the ones "owned"/downloaded by your app. Any others can only be deleted outside of your app. Your app also needs to handle a situation where something downloaded was deleted outside of your app too. I believe this is the designed and intended behaviour.

    So the only way to guarantee that the navigation works is leaving the file stored in the flash which is probably not what a user expects nor wants though.

    I'd have thought this is what they'd expect and even want. They may want to navigate a course which was downloaded by an app without needing to go back into that app.

    You are lucky, at one point, if you deleted something after getting the intent, and then used exitto, the watch crashed! I'd want/expect the exitto to fail if you have removed the course after getting an intent.

    I think you are expecting to be able to download a course, and have this temporarily available to your app while you navigate, but not be permanently stored on the watch, but this is not how this was designed. You can download workouts & courses in your app, and you can use them, but to a certain extent these are independent actions.

  • Thanks for your answer.

    I think there are a lot of things around courses that can be improved. Third-party developers have little to no control over them, except for downloading and deleting the downloaded ones.

    For example, the getName() method returns a truncated name with only 15 characters.

    Then you have no access to the activity stored in the file, nor the waypoints it contains.

    I think you are expecting to be able to download a course, and have this temporarily available to your app while you navigate, but not be permanently stored on the watch, but this is not how this was designed. You can download workouts & courses in your app, and you can use them, but to a certain extent these are independent actions.

    Yes, I would also like to give users a preview of the course (as asked in this thread) before deciding to save it or starting it right away.

    Garmin doesn't have the ecosystem for getting detailed information about courses. Other platforms have descriptions, images, hints about dangers, closures along the course, etc.

    Why would they make it so hard for others to make use of these platforms, if they won’t do it themselves?

    Just my two cents...

  • So the only way to guarantee that the navigation works is leaving the file stored in the flash which is probably not what a user expects nor wants though.

    If you really want to delete the downloaded course FIT file after the user is finished with it, I guess you could implement a background process and use registerForActivityCompletedEvent to delete the course when the next activity is completed (presumably it will be the one which utilized the downloaded course for navigation). 

    Ofc there's a couple of holes here:

    - it won't work if the user just cancels / denies the intent to launch the course

    - it probably won't work if the user discards the activity (at least that's my guess - haven't tried it myself)

    You could probably plug those holes by saving the course name to app storage, as part of a list (array) of courses to be deleted on next startup. If the app is launched again, then it's probably safe to assume the user doesn't need the last course anymore, right? Except for the edge case where the user tries to launch your app during an activity - you might be able to address this edge by using Activity.getActivityInfo() to determine whether an activity is currently running (e.g. if getActivityInfo is null or ActivityInfo.timerTime / elapsedDistance is null, it's probably safe to assume no activity is currently active)

  • Why would they make it so hard for others to make use of these platforms, if they won’t do it themselves?

    My 2 cents is I don't think Garmin really wants 3rd party apps to be able to do anything better than native apps, just different

    For example, navigation is a built-in feature so Garmin doesn't want 3rd party apps to do navigation better than built-in Garmin navigation. (Otherwise it takes away from Garmin's ability to use navigation as a selling point for watches.)

  • I don't know how the managers at Garmin think, but selling a good hardware with good support for 3rd party devs is also a good selling point. After all it's possible that some users buy Garmin because they want to use it with Komoot.

  • Yes but I think we all know that 3rd-party Connect IQ apps are an intentionally crippled afterthought in the Garmin ecosystem (with the exception of watchfaces and music providers). Garmin devices are nothing like modern general-purpose smartwatches such as Apple Watch and Samsung Galaxy Watch, where 3rd party apps are arguably indispensable.

    I will again argue that most normie Garmin users - such as runners - either have no idea what Connect IQ is or care very little. At most they use Spotify and maybe a 3rd party watchface.

    But even an Apple Watch dev recommends using the built-in Workout app for running, arguing that built-in apps have access to more information than 3rd party apps and also have better input capabilities (sound familiar?)....

    I do think that if the Connect IQ store disappeared tomorrow, very few Garmin users would notice, whereas Apple Watch users would revolt if the Apple app store stopped supporting Apple Watch.

    (Then again, Garmin has shown that they "care" enough about CIQ that they won't deprecate certain functionality that's used by old apps, and they reversed the removal of drawAngledText/drawRadialText from FR165/165M)

  • If you really want to delete the downloaded course FIT file after the user is finished with it, I guess you could implement a background process and use registerForActivityCompletedEvent to delete the course when the next activity is completed (presumably it will be the one which utilized the downloaded course for navigation). 

    Ofc there's a couple of holes here:

    - it won't work if the user just cancels / denies the intent to launch the course

    - it probably won't work if the user discards the activity (at least that's my guess - haven't tried it myself)

    You could probably plug those holes by saving the course name to app storage, as part of a list (array) of courses to be deleted on next startup. If the app is launched again, then it's probably safe to assume the user doesn't need the last course anymore, right? Except for the edge case where the user tries to launch your app during an activity - you might be able to address this edge by using Activity.getActivityInfo() to determine whether an activity is currently running (e.g. if getActivityInfo is null or ActivityInfo.timerTime / elapsedDistance is null, it's probably safe to assume no activity is currently active)

    Yea, I did something like that with a dictionary tracking the last course launched, but it's obviously a very ugly hack.

    Thanks for your input.