Tracks2Miles 1.1.9 release

So the My Tracks guys released version 1.1.10 last week. This normally would be a good thing as they have been adding lots of nice new features and generally improving things.

Unfortunately in this release they also included a feature that stops 3rd party apps using their database without the user having to go into the their settings and allowing it.

I don’t agree with what the change is looking to achieve, My Tracks already has a set of Permissions that need to be requested by an application before it can access the data. If the user does not want to grant access then they should not install the 3rd party apps. I know nobody really reads closely the list of Permissions apps ask for at install time, but this is a problem for the Market application to solve by better high lighting the Permissions being asked for and explaining the consequences of accepting them.

On top of that there is no easy way to check if the “Allow access” option is set before you try and access the data. I will be raising a issue about this shortly as well as submitting another change to mean that I don’t have to try and guess the name of the track being exported.

It also would have been nice to get more than a couple of hours notice that the this new “feature” was about to ship. While I know it has been discussed on the site, I have a not been following the updates recently because the day job has been particularly busy. It would have at least been courteous to send the email that notified the owners of those with apps about the change a little sooner. So we had time to make the required changes rather than just get a whole slew of bug reports.

Anyway that’s the bitching out of the way. There is now a new version of Tracks2Miles that will show a dialog box if it can not access the data and return you to My Tracks to enable the access to the data.

You can grad the latest version from the Market here

Tracks2Miles Facebook logon

Ever since Tracks2Miles shipped users have been having problems authorising the app if they choose to log in with their Facebook credentials.

The problem is that once the user had logged into Facebook it would redirect to a blank white page.

Last night I had another look at what was causing it.

To start with I added a Log statement to the shouldOverrideUrlLoading() method to print out the URL that was being loaded. This implied that the last URL loaded was from Facebook:

http://www.facebook.com/connect/uiserver.php?method=permissions.request&app_id=xxxxxxxxxx&display=touch&redirect_uri=https%3A%2F%2Fapi.dailymile.com%2Flogin%2Ffacebook%2Fcallback&state=next%3D%252Foauth%252Fauthorize%253Fresponse_type%253Dtoken%2526client_id%253Dxxxxxxxxxxxxxxxxxx%2526redirect_uri%253Ddm%253A%252F%252Flocalhost%252Ffoo&type=web_server&fbconnect=1&perms=email%2Cpublish_stream%2Coffline_access&from_login=1&refsrc=http%3A%2F%2Fm.facebook.com%2Fsetup_machine_mobile.php&refid=0&m_sess=MUm3C-eKFY7K8h&_rdr

I poked around at this for a while, but didn’t get very far, until Chris Banes pointed me at the source for the facebook-android-sdk, specifically the FbDialog.

When I added some trace to the onPageStarted() method I made some progress, the output from this implied that Facebook page had actually loaded successfully and redirected back to dailymile.

https://www.dailymile.com/login/facebook/callback?code=HphJjEM9nKsSez0ZW28W-FcvN80xR049KtQtk7CrykM.eyJpdiI6ImxGNVEyQ0FuSlF1X0xKdWJoU1MtZncifQ.yaVPEGNBOBPMQtZjrE431mw6a4-6yXUrvz0XrCd2ub44KKArQXpfiydYvhocYZuV0FW9mIO_3KLjBEO1XejL-EoplURcmbpoA3ueXjQJmvsu9Gf0Vaj7CLOdLOOpFw-d&state=next%3D%252Foauth%252Fauthorize%253Fresponse_type%253Dtoken%2526client_id%253Dxxxxxxxxxxxxxxxxxxxxxxxx%2526redirect_uri%253Ddm%253A%252F%252Flocalhost%252Ffoo

I had tried loading this new URL with Firefox on the desktop and immediately got a certificate mismatch error. The URL was hosted on www.dailymile.com but the cert was for api.dailymile.com

I was a little surprised that default WebView just swallowed this with no error messages, but a bit of googling and found the following blog post about how to work round the certificate miss match and even how to make it work with Android builds before 2.2

I also pointed the problem out to Ben from dailymile and he has fixed the cert mismatch with in a couple of hours.

There will be an updated version of Tracks2Miles in the next few days with these changes (just to be safe) and a couple of other updates around distance units.

Tracks2Mile 1.1.4 – With automatic details import

After discovering that my patch for My Tracks had been pulled just before their last release (1.1.5) I’ve been looking for another way to get the information about time and distance.

After another closer look at the instructions 3rd party use instruction on the wiki and it’s possible to access the My Tracks database directly. Running a query that filters on the workout title, which I can get from the GPX files name, I can get hold of all the information. It is possible to have multiple workouts with the same name so I’m picking the last one added to the db since this has to be the most likely one you’ll be wanting to upload.

Since I’m reading direct from the database there is also the problem that if the My Tracks guys change the table layout then I could have a problem. The API provides a method that returns a Track object which holds the data but you can only use this if you know workout id, but this available at the moment.

I’ll probably stick a new patch in for My Tracks to pass the workout id so I don’t have to make this assumption, but it should be good enough for now.

Other fixes include:

  • One to stop caching photos in memory before writing them to the sd card to prevent OutOfMemoryErrors
  • Closed a couple of windows where the database was accessed after it’s been closed.

Grab it from the Android Market here

My Tracks patch pulled

So it looks like my patch to My Tracks to get it to expose the extra information needed for Tracks2Miles got pulled just before the last release because it broke the export to GMail (and dropbox).

It’s a shame it got spotted so close to the release of My Tracks 1.1.5 I didn’t get chance to look at before it went out.

It looks like Android resolves and unpacks all the Parcellable extras upfront even if they are not used by the receiving Activity or Service. So apps not expecting the Track object I was using fail with ClassNotFoundException because it’s not available.

I’ll try and find some time to come up with a new solution as soon as I get some time to think about it properly.

Tracks2Miles 1.1.0

The latest Tracks2Miles update

Added a timeline view to see what you friends have been up to.

*** Edit ***

I’ve just noticed that on some phones that after the update the launch icon will still open the Activity for publishing a new workout rather than the Timeline Activity. This is a “feature” of some of the launchers, you may need to restart your phone to get it to see the update.

*** Edit ***

Fixed up a couple of race condition type problems.

Updated the code to import from My Tracks to use the patch that has been accepted for the next release.

My Tracks Patched

The guys at My Tracks have integrated the changes I sent to enable more data to be passed with the GPX file. There are some slight changes needed to the currently released version of Tracks2Miles but I will push a new version in the next couple of days to be ready for the next My Tracks drop.

I don’t know when the next version of My Tracks will ship yet, but we will be ready,

In the meantime here are the details of the change so others can use it to build similar add-ons for any other site (why they would want to use anything but dailymile?).

As mentioned back in the first post on this subject your going to need an Intent filter that will trap when My Tracks is looking to export a GPX file (the changes to My Tracks apply to all file types, but I’m only going to talk about GPX here). The following is what I’ve been using for Tracks2Miles:

 <activity android:name=".Export"
      android:label="@string/app_name" android:exported="true">
   <intent-filter>
     <action android:name="android.intent.action.SEND" />
     <category android:name="android.intent.category.DEFAULT" />
     <data android:mimeType="application/gpx+xml" />
   </intent-filter>
 </activity>

This hooks the “android.intent.action.SEND” action and filters it for the mimeType “application/gpx+xml”. So in the Activity that gets called when an intent matching this is broadcast you will need a onCreate method that looks something like this.

public void onCreate(Bundle savedInstanceState) {
  Intent intent = getIntent();

  if (intent.getAction().equals(Intent.ACTION_SEND)) {
    if (intent.hasExtra("com.google.android.apps.mytracks.TRACK")) {
      Track track = (Track) intent.getParcelableExtra("com.google.android.apps.mytracks.TRACK");
      ...
    }

    Uri gpxURI = (Uri)intent.getExtras().get(Intent.EXTRA_STREAM);
    ...
  }
}

Where Track is an instance of com.google.android.apps.mytracks.content.Track. You will need to grab this and the 2 classes in the package com.google.android.apps.mytracks.stats so they can be on the classpath for getParcelableExtra to find them. From the Track object you can get hold of name, time and distance of the workout and also there is a Statistics field that has info on average/max speed, elevation information.

I’m planning on writing a My Tracks wiki page about this some time soon where I’ll go in to a little bit more detail but this should get most people started.

Tracks2Miles 1.0.4

A quick update about the 1.0.4 * update release of Tracks2Miles.

  • Added some better error path handling to make it a bit more graceful should it fall over.
  • Added a local DB to cache route information, this is for 2 reasons. Firstly to make it quicker to just pick a route without having to wait for the list to be downloaded and secondly as a work around for the missing distance info in routes uploaded via the API. One of the side effects of this is that previously uploaded routes with no distance will not be shown in the list. Look at the end of the post for a way to fix these routes.
  • Added a bit more validation before posting, this should make it harder to post routes without titles or time and distances. A dialogue will ask if you really want to do this before posting.

I’ve also found a way to fix the uploaded routes missing distances. If you view the routes on the dailymile website, then hit the edit link at the top it will open the route editor. At this point it will recalculate the distance and you can just hit the Update button in the bottom right hand corner. The route should now have a valid distance.

Based on Dan’s comments on the announcement entry, I’m planning on looking to see if I can identify an existing route before posting a new one from My Tracks, this will reduce upload time and allow for dailymile to track your best time. To keep things easy it will probably just be based on the name of the track and distance.

I have added the following short video to the Android Market entry.

* 1.0.2 & 1.0.3 wouldn’t work on 2.1 due to using a method in API v8, I’ll remember to check 2.1 in the emulator before uploading next time

Announcing Tracks2Miles

OK, so the last 3* posts have been about the development of this so I guess you all knew it was coming, but now after some kind folk (Thanks @davidgeorgeuk, @bodonovan, @TheMightyAl & @ragtag) beta tested it for me it’s time to release it to the world.

A Friday afternoon chat between myself, Karl Roche, Brian O’Donovan and Dale Lane about tracking exercise habits with the website dailymile led to wondering why there was no Android app for it yet. A quick look at the API suggested it shouldn’t be too hard run something up. A short weekend of hacking later the majority of Tracks2Miles was done.
Tracks2Miles Icon
Tracks2Miles is an Android application to take workouts recorded with My Tracks and uploads them dailymile.

Rather than reinvent the wheel and write a full GPS tracking app I decided to see how easy it would be to extend one of the existing apps. My Tracks was one of the first training apps released for Android so it seamed like a good place to start. My Tracks have released a library to allow embedding the GPS tracking into new apps, but even this looked like a lot of work, but My Tracks also has a feature to “Share with friends…” which uses the android.intent.action.SEND intent action to allow other apps to forward on the data in a number of formats, one of which is GPX. This made writing the Tracks2Miles very easy.

Current Features:

  • Export routes from My Tracks – use the “Share with friends…” menu option to share the current track
  • Post workouts without using My Tracks – Tracks2Miles can be launched directly to upload a workout without uploading a new track e.g. treadmill seasons
  • Existing route reuse – start Tracks2Miles from the launcher and hit the “Use existing route” button and you can use routes already uploaded to dailymile

Possible Upcoming Features:

  • Support other apps – add support for exporting from apps like Endomondo or Runkeeper if they can export GPX files
  • Export any GPX – search the file system and upload any GPX found
  • dailymile timeline – a way to see what everybody else has been up to and add comments and motivation
  • Offline caching – save on bandwidth and API calls
  • User preferences – store defaults for Rating and workout type type
  • Contact syncing – add your running buddies to your phones contact list
  • Retry on network loss – uploading long routes can take a while over slow networks so a bit more fault tolerance would be good
  • Widget – because every app needs a widget

Known issues:

  • Facebook login not working – When authorising Tracks2Miles using an account created using your Facebook account it says password is wrong. This looks like either a problem on the dailymile or Facebook side of things, I have reported it
  • Time and distance not filled in when exporting from My Tracks – a patch to make this happen have been submitted to My Tracks, hopefully it will make it into the next release.
  • Reused routes have zero length – Some routes returned by dailymile are shown to have zero length so the distance is not filled in when using them. I have reported this to dailymile.

I’ve tested this on a HTC Desire, a ZTE Blade (Orange San Francisco) (updated to 2.2), a Samsung Galaxy and a Motorola Defy devices along with in the emulator running 2.1, 2.2 and 2.3. It should run on Android 2.1 or newer.

The Android Market URL is https://market.android.com/details?id=uk.me.hardill.dailymile or us the following QR code:

*

  1. My Tracks to dailymile GPX route exporter – part 1
  2. My Tracks to dailymile GPX route exporter – part 2
  3. My Tracks to dailymile GPX route exporter – part 3