Closed yusmi25 closed 2 years ago
It looks like there is a bug in the UploadActivityRequest model. I imported the code locally and fixed it and got it working with my own account. The main change that needs to be done is in the serialization/deserialization on the UploadActivityRequest object. They might have updated their property names to be underscore now instead of title case. These are the corrected serialization/deserialization methods.
I was going to push a pull request to fix it, but I believe I need permissions first.
UploadActivityRequest.fromJson(dynamic json) { name = json['name']; description = json['description']; isTrainerActivity = json['trainer']; isCommuteActivity = json['commute']; dataType = json['data_type']; externalId = json['external_id']; }
Map<String, dynamic> toJson() { var map = <String, dynamic>{}; map['name'] = name; map['description'] = description; map['trainer'] = isTrainerActivity; map['commute'] = isCommuteActivity; map['data_type'] = dataType; map['external_id'] = externalId; return map; }
As far as example code, this is what I used:
First you need to ensure you confiure your app link for authorization redirect:
`
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST -->
<data
android:scheme="YOUR_SCHEME"
android:host="YOUR_HOST" />
`
The scheme and host can be anything, just ensure they are unique since they are globally shared across all apps.
For IOS in Info.plist:
`
hi @mstreeter24 first of all thank you! a pull request with your fix would be a great contribution if you can, if not, can you please attach the modified files in here?
@dreampowder I believe somebody who has permissions would have to give me permission to edit the repo. I can add my changes on a bugfix branch if you give me permission.
If not the code fix is in my first post. Under domain/model/model_upload_request.dart replace the from and to json functions with:
UploadActivityRequest.fromJson(dynamic json) { name = json['name']; description = json['description']; isTrainerActivity = json['trainer']; isCommuteActivity = json['commute']; dataType = json['data_type']; externalId = json['external_id']; }
Map<String, dynamic> toJson() { var map = <String, dynamic>{}; map['name'] = name; map['description'] = description; map['trainer'] = isTrainerActivity; map['commute'] = isCommuteActivity; map['data_type'] = dataType; map['external_id'] = externalId; return map; }
@yusmi25 I am guessing you fixed your fault issue since I don't see the message even though I got the email? My guess is it was unrelated and something to do with payload format or something along those lines. This is the general flow I use to upload a file.
RecordedRoute is just an object with a list of points that have latitude, longitude, time stamps and altitude. It also has a stravaSync bool value that stores whether the route has already uploaded to Strava and a Strava upload id so it can get the status of unfinished uploads. response.error != null || response.externalId != null; is checking whether the upload errored out or succeeded.
From there I generate a GPX file with the gpx flutter library and then save it to a temporary directory before passing it to the uploadActivity call.
void syncWithStrava(RecordedRoute recordedRoute) { if (recordedRoute.stravaSync) { return; } Completer<TokenResponse> completer = Completer<TokenResponse>(); _stravaClient.authentication.authenticate( scopes: [AuthenticationScope.activityWrite], redirectUrl: Uri.encodeComponent(APP_REDIRECT_LINK) ).whenComplete(() { if (recordedRoute.stravaId != null) { _stravaClient.uploads.getUpload(recordedRoute.stravaId!).then( (UploadResponse response) { recordedRoute.stravaSync = response.error != null || response.externalId != null; _trailRouteDao.updateStrava(recordedRoute); } ).catchError((_) => Future.value(null)); } else { recordedRoute.getGpxFile().then((io.File gpxFile) { _stravaClient.uploads.uploadActivity( UploadActivityRequest(file: gpxFile, name: recordedRoute.name, dataType: 'gpx') ).then((UploadResponse response) { recordedRoute.stravaId = response.id; _trailRouteDao.updateStrava(recordedRoute); try { gpxFile.deleteSync(); } catch(e) { debugPrint('Exception during file remove.'); } }).catchError((_) => Future.value(null)); }); } }).catchError((_) => completer.future); }
@mstreeter24 I updated the code for UploadActivityRequest serializer. are the any other issue with the code?
@dreampowder There shouldn't be. That was the only change I made to my local copy to get it working. I was just giving him an example of how to use the library to get past his Fault issue which was probably related to a badly formatted GPX file. My example ignores exceptions and faults though, since I don't do anything about them anyway.
hello @dreampowder, Is there any sample code to get current user when Application startup and example to upload activity. when I using version ^1.2.2+62 I'm using this code to upload activity and get current User ` // examples.dart
// Examples to use strava_flutter import 'dart:async'; import 'dart:io'; import 'package:flutter/services.dart' show rootBundle; import 'package:path_provider/path_provider.dart'; import 'dart:typed_data'; // Needed when declaring ByteData
// import 'package:strava_flutter/API/constants.dart'; import 'package:strava_flutter/errorCodes.dart' as error; import 'secret.dart';
// Used by uploadExample import 'package:strava_flutter/strava.dart'; import 'package:strava_flutter/Models/fault.dart'; import 'package:strava_flutter/Models/stats.dart'; // Test
// Used by segment and segmentEffort import 'package:strava_flutter/Models/segment.dart'; import 'package:strava_flutter/Models/segmentEffort.dart';
// To test getLoggedInAtletheActivities import 'package:strava_flutter/Models/detailedAthlete.dart'; import 'package:strava_flutter/Models/activity.dart';
/// Example showing how to upload an activity on Strava /// /// Use file Bormes.gpx in assets /// /// Should appear on your activities 6 Feb. 2019 /// /// Under the title Bormes3 /// Future uploadActivity(String secret, String path) async {
String titleName;
// Do authentication with the right scope
final strava = Strava(
true, // To get display info in API
secret);
Fault _fault = Fault(error.statusOk, 'Upload succesful');
bool isAuthOk = false;
isAuthOk = await strava.oauth(clientId, 'activity:write', secret, 'auto'); print('---> Authentication result: $isAuthOk'); if (isAuthOk == false) { _fault.statusCode = error.statusAuthError; _fault.message = 'Authentication has not been succesful'; return _fault; }
var hour = DateTime.now().hour; if (hour < 12) { titleName = 'Morning Ride'; } if (hour < 17) { titleName = 'Afternoon Ride'; } else { titleName = 'Evening Ride'; }
Fault fault = await strava.uploadActivity( titleName, 'Uploaded By Qimtronics', path, 'fit');
return fault; }
Future autStrava(String secret) async {
// 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('---> Authentication result: $isAuthOk'); return isAuthOk; }
Future deAuthorize() async {
// need to get authorized before (valid token)
final strava = Strava(
true, // to get disply info in API
secret, // Put your secret key in secret.dart file
);
var fault = await strava.deAuthorize();
return fault;
}
`
Thank You.