rw_tcx 0.0.1

rw_tcx #

name: rw_tcx description: A simple package to read and write TCX file using Dart

version: 0.0.1+6

Getting Started #

Please note that this package is for the moment a work in progress

It is a Dart only package, Flutter is not needed

The test file sample1.tcx is coming from Garmin Connect export

How to install #

Check on pub.dev/packages to see how to install this package

How to use it #

There is only 2 APIs

  • readTCX
  • writeTCX

If you have any problem, please post a new issue

Tested on: #

Thanks #

License: #

rw_tcx is provided under a MIT License. Copyright (c) 2019 Patrick FINKELSTEIN

[0.0.1] - TODO: Add release date.

  • TODO: Describe initial release.

example/lib/main.dart

import 'package:flutter/material.dart';

import 'package:flutter/services.dart' show rootBundle;

import 'secret.dart'; // Where Strava app secret and clientId stored
import 'package:rw_tcx/rw_tcx.dart';
import 'package:rw_tcx/models/TCXModel.dart';

import 'dart:io';   // Needed for File
import 'package:path_provider/path_provider.dart';  // Needed for getApplications

import 'package:strava_flutter/strava.dart';
import 'package:strava_flutter/Models/fault.dart';

// Used by Google Service Account
// import "package:googleapis_auth/auth_browser.dart";
import 'package:googleapis/drive/v3.dart' as drive;
import 'package:googleapis_auth/auth_io.dart';
import 'dart:io' as io;

// Used by Google sign in 
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';


import 'package:http/http.dart'
    show BaseRequest, Response, StreamedResponse;
import 'package:http/io_client.dart';
class GoogleHttpClient extends IOClient {
  Map<String, String> _headers;

  GoogleHttpClient(this._headers) : super();

  @override
  Future<StreamedResponse> send(BaseRequest request) =>
      super.send(request..headers.addAll(_headers));

  @override
  Future<Response> head(Object url, {Map<String, String> headers}) =>
      super.head(url, headers: headers..addAll(_headers));

}



main(List<String> args) async {
  print('Start of rw_tcx example');


  // First init of Strava API stuff
  // Do authentication with the right scope
  final strava = Strava(
      true, // To get display info in API
      secret);

  bool isAuthOk = false;

  isAuthOk = await strava.oauth(clientId, 'activity:write', secret, 'auto');

  print('---> Strava Authentication result: $isAuthOk');


  // Start Google Auth to try access Google Drive

  final FirebaseAuth _auth = FirebaseAuth.instance;
  final GoogleSignIn googleSignIn = GoogleSignIn(
    scopes: ['https://www.googleapis.com/auth/drive'],
  );

  final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
  final GoogleSignInAuthentication googleSignInAuthentication =
      await googleSignInAccount.authentication;


   final AuthCredential credential = GoogleAuthProvider.getCredential(
    accessToken: googleSignInAuthentication.accessToken,
    idToken: googleSignInAuthentication.idToken,
  );

  // final FirebaseUser user = await _auth.signInWithCredential(credential);
  AuthResult authResult = await _auth.signInWithCredential(credential);

  assert(!authResult.user.isAnonymous);

 
  assert(await authResult.user.getIdToken() != null);

  final FirebaseUser currentUser = await _auth.currentUser();
  assert(authResult.user.uid == currentUser.uid);

  print('signInWithGoogle succeeded: ${authResult.user}');

  var client = GoogleHttpClient(await googleSignInAccount.authHeaders);

  var driveApi = drive.DriveApi(client);

  var fileList = await driveApi.files.list();

  // Display for 10 file names
  fileList.files.forEach((file) => print('---${file.name})'));
  

  


/*****  Using Google Service Account
  AuthClient client = await clientViaServiceAccount(
  ServiceAccountCredentials.fromJson({


  "type": "service_account",
  "project_id": "leafy-stock-249015",
  "private_key_id": "576daafdd8808aba24039a168c93d445082c140f",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCSZ2SBOpCwOrNM\n+49UKa3nUjSOQFLYlsDtIXODc78MyCEJjacY6wq3oZCpOmrWaFyhLkPEa/yqzfu0\n7Y69QIUsD/XZRJcYkDetqYONDQbZHxz/SwmZFNkSQmvapTiFro5II0eOvkmbwvV3\nfmzK3B2xmsClyoNn3Hv8zxfPLyh6t3Z00fdsuPD6E3fTsrkmbLZFXgsYGhyW3Oqe\n3JO3WhxF11537DFxu+GksCqFKQnN+iYt8Tb3hWQj8eanvOwNuCHX6+6B+6Uc8amh\nXqTMMPTpSTX3KeoQa52Z7MRIwallTIPvNb0nYodO+GsHYi82koshKvEKXEWqib6b\nl17wZzPFAgMBAAECggEAFDCRpyf6Q8YB67K2DDS9Pe0pFe71SIIts+X3kKAPL5uP\nwXSun7HrkJxaye5Q79AvlK4VJrV/qtcXiFbJvFFKrDi9PjZbzJri2sj0PSjtPKxc\n6ttLGmMfdl8A5wOpnPc6uY8H82hMLWCq9Pd92FHs/wz+K+mWypAY7H8WDk/iD14f\n0nmN1qzOJlny8a2Q+7aG/gZLTnVLpWSku4WcnHuTRgLs5f9siGA8MlgbQNd2f1A1\n/qn+I2d9j2gM3Cw+0do7FtRtlblBZ5SyWhB8WGzKr2u1fVsdhk7itCJEHHgwSWvX\n2vEA3E84mNYZrLTSgTKCyO2dVxdlmn9T2j2jGUWKtwKBgQDKmLywygKTfAJd3Qot\nCPWXshasSxgpHfNDiBMZazIVR12KfnGWm3L03PMOW6LvuT7eXQqWNPjtKF6Q+rH0\nO61nPzIel8dyOru7v7WyLXD3YXV/AobmDvbjUIFEiK6sGlcfwcuxcEM/Eq43ikVS\nU9MwBgMFbtpIzFIsAC+XfaEQVwKBgQC4/sHCVeAu4iIA2EFqMANuy8egruZLCOzD\n0gbg7opaAi+DpVzA9ZAJ1v4m2NjYSGLsyo+jDDvGt4LhKG4OHU94tJCAhO5Zd6ly\nXH4o+9eWROWrt9G5DKp5iNFTls4YSKV32crUaR3UrjaweaXPXodngnTqTt8Y4U52\nvg1lundbQwKBgF2AHCVjNcknRFhZeSbLqby23ivqBF6Fig2ysU3b4SNc6ljOflHJ\nsEY96pbHx+znC5LIUeh8zh11sh8q9BIJsL+jtNfVqKCZZqcBlTOEMUyaWAWj/uoS\nIfNK5j3g7uxSw77OS9m6O+7SCkFruQ6DzUWuoJpTTL6oPYw9EbnSqxDFAoGBAIAn\n9GDFjxXLkFTXe5Gti2NBBp15LI7EswkBQcSnW+743qOrdfMy6sL2ToDo7mf+1ZFG\nznTcr7h9PszubjeW9IwhQo3WCSyvqhJQoxGPTg2K0zS/lilE7gBd2O24ZjQKd57s\noQe/fmvs+HQPAeADk3gQtx/u3bzlsK6wAKX9pFvzAoGAODyzVKbaZbIUy7lx2m8I\naohE/wPbA/4yn/JQbpRoF13oySeHboPx9/MFe6CTaXRnQJOpF88q+LvdD/QWqDyf\nhFmIkL1rEu3QWf5MzCUWd+l/uvRXAtJSXTuGOiL00LLcbUis9ZPD+UPWr2emPKeN\nKz5Vke8Evo5F8GoNWMmpjeA=\n-----END PRIVATE KEY-----\n",
  "client_email": "test2-635@leafy-stock-249015.iam.gserviceaccount.com",
  "client_id": "112867373329814899435",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/test2-635%40leafy-stock-249015.iam.gserviceaccount.com",
     }),
     ['https://www.googleapis.com/auth/drive']);

  var driveApi = drive.DriveApi(client);
  // var driveApi = DriveApi(client, servicePath: 'upload/drive/v3/files');
*****/

  final directory = await getApplicationDocumentsDirectory();
 
  String path = directory.path;

  // String result = await rootBundle.loadString('assets/vewd.txt');
  var result = await rootBundle.load('assets/vewd.txt');

  var fileToUpload = await io.File('$path/toto.txt').writeAsString('This is the end my friend');
  
  // Not working for the moment 
  // Can not find the file (path problem?)
  // List<int> res2 = await fileToUpload.readAsBytes();

  
  var mediaContent = drive.Media(fileToUpload.openRead(), fileToUpload.lengthSync());
  drive.File newFile = drive.File.fromJson({
    'mimeType': 'text/plain',
    'name': 'sample2.txt', 
  });
  
  drive.UploadOptions options = drive.UploadOptions.Default;
/****
  await driveApi.files.create(File()..name = 'sample2.tcx',
  uploadMedia: Media(fileToUpload.openRead(), fileToUpload.lengthSync()));



var fileList = await driveApi.files.list();



   await driveApi.files.create(newFile,
      uploadMedia: mediaContent, uploadOptions: options );
****/





  print('Read a TCX file');

  // Use the asset file to test without having to create internally a ride
  TCXModel rideData = TCXModel();

  String contents = '';

  try {
    // Read the test file sample1.tcx in assets

    contents = await rootBundle.loadString('assets/sample2.tcx');

    print('contents $contents');

    rideData = readTCX(contents);
  } catch (e) {
    print('error loading assets file:  $e');
  }

  print('Write a TCX file');

  TCXModel tcxInfos = TCXModel();
    
  tcxInfos.points = rideData.points;
  tcxInfos.swVersionMajor = 'SWMajor';
  tcxInfos.swVersionMinor = 'SWMinor';
  tcxInfos.partNumber = 'Part Number';

  await writeTCX(tcxInfos, 'generatedSample.tcx');

  print('End of write TCX test');


  // Now use Strava API to upload the generatedTCX
  // Strava authentication has been done previously

  String dirUpload = (await getApplicationDocumentsDirectory()).path;



  Fault fault = await strava.uploadActivity(
      'B88888', 'It is working!', '$dirUpload/generatedSample.tcx', 'tcx');


  print('This is the end!!');


  

}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  rw_tcx: ^0.0.1

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:rw_tcx/rw_tcx.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
10
Health:
Code health derived from static analysis. [more]
99
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
90
Overall:
Weighted score of the above. [more]
53
Learn more about scoring.

We analyzed this package on Aug 21, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19
  • Flutter: 1.7.8+hotfix.4

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Health suggestions

Fix lib/wTCX.dart. (-1 points)

Analysis of lib/wTCX.dart reported 2 hints:

line 10 col 8: Unused import: 'logTool.dart'.

line 154 col 18: The getter '_localFile' isn't used.

Fix lib/rTCX.dart. (-0.50 points)

Analysis of lib/rTCX.dart reported 1 hint:

line 133 col 14: The value of the local variable 'dateTime' isn't used.

Format lib/logTool.dart.

Run flutter format to format lib/logTool.dart.

Format lib/models/TCXModel.dart.

Run flutter format to format lib/models/TCXModel.dart.

Format lib/rw_tcx.dart.

Run flutter format to format lib/rw_tcx.dart.

Maintenance suggestions

Package is pre-v0.1 release. (-10 points)

While nothing is inherently wrong with versions of 0.0.*, it might mean that the author is still experimenting with the general direction of the API.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
path_provider ^1.2.0 1.2.0
Transitive dependencies
collection 1.14.11 1.14.12
meta 1.1.6 1.1.7
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test