sweetzpotas / stravazpot-android Goto Github PK
View Code? Open in Web Editor NEWA fluent API to integrate with Strava on Android apps
A fluent API to integrate with Strava on Android apps
hi there, it seems virtual runs are not supported (the type is not listed in the model folder of the library, under activitytype). When reading a virtual run, it is reported as virtual ride from the library. Any chance this can be extended? Thank you.
I have an issue sending TCX file.
At the end of transmission I have following error:
java.lang.NumberFormatException: Expected an int but was 2179799777 at line 1 column 17 path $.id
Debugging I found that happens when Strava anwer to upload with code 201 "Your activity is still being processed." that is considered error and there is an exception during parsing the answer.
Looking at:
https://developers.strava.com/docs/uploads/
this code should interpreted as success?
When I try to signIn to Strava with this code :
val intent = StravaLogin.withContext(getContext())
.withClientID(CLIENT_ID.toInt())
.withRedirectURI("some URL")
.withAccessScope(AccessScope.VIEW_PRIVATE_WRITE)
.makeIntent()
startActivityForResult(intent, 1)
then I clicked to "Log in using Facebook" and next page is
"Log in using Google" and by email Password is working perfect this error is only when I try to log in using facebook.
I am trying to access the Segments part of the API, specifically the exploreSegementsInRegion, and I believe I have it set up correctly, but I am getting an error as such:
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
As far as I know, it is not an issue with my code. Really all I have so far is what is shown in the Readme(which is well done by the way).
I know that I get back a response because I can see it in Android Monitor, but I think when it is trying to convert it to the List it is throwing an error.
The boyd of my function looks like this
try {
AuthenticationConfig config = AuthenticationConfig.create()
.debug()
.build();
AuthenticationAPI api = new AuthenticationAPI(config);
TOKEN = api.getTokenForApp(AppCredentials.with(Integer.parseInt(getString(R.string.clientID)), getString(R.string.clientSecret)))
.withCode(CODE)
.execute();
CONFIG = StravaConfig.withToken(TOKEN.getToken())
.debug()
.build();
SegmentAPI segmentAPI = new SegmentAPI(CONFIG);
segments = segmentAPI.exploreSegmentsInRegion(Bounds.with(Coordinates.at(SW_LAT, SW_LONG), Coordinates.at(NE_LAT, NE_LONG)))
.forActivityType(ExploreType.RIDING)
.execute();
System.out.println("here");
}
catch (Exception e)
{
e.printStackTrace();
}
That code is in the doInBackground section of an AsyncTask, but I again I believe that is all correct to my knowledge.
The first three lines of the traceback are:
at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:350)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61)
Let me know if you need anymore information and thank you.
In application I should store token and use it in future for calls to Strava, or I should store code, and obtain token at lest on every new start of app? With sore token is problem, tat you not allow to access it via your class;-) I can remove "Bearer" from string representation of token but...
Edit: like I see for example in Strava library for python, they suggest to store token. So maybe getTokien will be good idea?;-) I can also serialize Token object:)
When downloading activities generated via a Garmin, i.e. fully populated, the Temperature field of Activity causes an error in JSON - OBJECT expected, number received.
I tried fully populating the Temperature class which seems to be a stub using Distance as a model, but the error still occurs.
Then spotted the type adapters - Temperature missing.
Fixes:
Temperature.java
public class Temperature {
private float celsiusDegrees;
public static Temperature celsiusDegrees(float celsiusDegrees) {
return new Temperature(celsiusDegrees);
}
public Temperature(float celsiusDegrees) {
this.celsiusDegrees = celsiusDegrees;
}
public float getCelsiusDegrees() {
return celsiusDegrees;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Temperature temperature = (Temperature) o;
return Float.compare(temperature.celsiusDegrees, celsiusDegrees) == 0;
}
@Override
public int hashCode() {
return (celsiusDegrees != +0.0f ? Float.floatToIntBits(celsiusDegrees) : 0);
}
@Override
public String toString() {
return String.valueOf(celsiusDegrees);
}
}
TemperatureTypeAdapter
public class TemperatureTypeAdapter extends TypeAdapter {
@Override
public void write(JsonWriter out, Temperature value) throws IOException {
out.value(value.getCelsiusDegrees());
}
@Override
public Temperature read(JsonReader in) throws IOException {
if(!in.peek().equals(JsonToken.NULL)) {
return new Temperature((float) (in.nextDouble()));
} else {
return null;
}
}
}
and register the typeadapter in config.java
Thank you for this amazing library. I noticed, that it's using retrofit, so my question Is if it's possible to enable response caching? https://futurestud.io/tutorials/retrofit-2-activate-response-caching-etag-last-modified
The Strava API has been updated to handle authentication inside the mobile app.
Hello,
could you please add state field in Request access?
I use backend to get and store STRAVA token and it's not a good way to pass state param into RedirectURI cause then SRAVA add one empty state param into redirect url
When login with Facebook, the login page width does not fit the activity.
Not sure why it's difficult to do but I followed the instructions and getting error.
Intent intent = StravaLogin.withContext(this)
.withClientID(STRAVA_CLIENT_ID)
.withRedirectURI("localhost")
.withApprovalPrompt(ApprovalPrompt.AUTO)
.withAccessScope(AccessScope.VIEW_PRIVATE_WRITE)
.makeIntent();
startActivityForResult(intent, REQUEST_STRAVA_LOGIN);
Got this error:
{"message": "Bad request","errors":[{resource":"Application","field":"redirect_uri", "code":"invalid"}]}
Edit: fixed my problem. It was the uri
When trying to obtain a Token using the example code in version 1.3.1
AuthenticationConfig config = AuthenticationConfig.create()
.debug()
.build();
AuthenticationAPI api = new AuthenticationAPI(config);
LoginResult result = api.getTokenForApp(AppCredentials.with(CLIENT_ID, CLIENT_SECRET))
.withCode(CODE)
.execute();
the retrofit and okhttp dependencies are not found and several classNotFoundExceptions are thrown.
such as:
E/AndroidRuntime: FATAL EXCEPTION: Thread-6
Process: bentest.com.strava_upload_andriod, PID: 12124
java.lang.NoClassDefFoundError: Failed resolution of: [Lokhttp3/Interceptor;
at com.sweetzpot.stravazpot.common.api.AuthenticationConfig$Builder.build(AuthenticationConfig.java:32)
at bentest.com.strava_upload_andriod.AuthThread.run(AuthThread.java:21)
Caused by: java.lang.ClassNotFoundException: Didn't find class "okhttp3.Interceptor" on path: DexPathList[[zip file "/data/app/bentest.com.strava_upload_andriod-2/base.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_dependencies_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_0_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_1_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_2_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_3_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_4_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_5_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_6_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_7_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_8_apk.apk", zip file "/data/app/bentest.com.strava_upload_andriod-2/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/bentest.com.strava_upload_andriod-2/lib/arm, /system/lib, /vendor/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at com.sweetzpot.stravazpot.common.api.AuthenticationConfig$Builder.build(AuthenticationConfig.java:32)
at bentest.com.strava_upload_andriod.AuthThread.run(AuthThread.java:21)
E/chromium: [ERROR:gl_context_virtual.cc(39)] Trying to make virtual context current without decoder.
However, this issue doesn't exist in version 1.3
I think this might have something to do with changing compile to 'implementation' instead of 'api'
I have an issue when calling listMyActivities()
This is the error log:
12-17 11:43:56.401 31885-32148/com.cajanegra.stam W/System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a name but was NULL at line 1 column 30 path $.biggest_ride_distance
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117)
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:89)
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at com.sweetzpot.stravazpot.common.api.StravaAPI.execute(StravaAPI.java:26)
12-17 11:43:56.402 31885-32148/com.cajanegra.stam W/System.err: at com.sweetzpot.stravazpot.athlete.request.GetTotalsAndStatsRequest.execute(GetTotalsAndStatsRequest.java:23)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at com.cajanegra.stam.PerfilActivity$5$1$1.doInBackground(PerfilActivity.java:477)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at com.cajanegra.stam.PerfilActivity$5$1$1.doInBackground(PerfilActivity.java:468)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:295)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at java.lang.Thread.run(Thread.java:818)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: Caused by: java.lang.IllegalStateException: Expected a name but was NULL at line 1 column 30 path $.biggest_ride_distance
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at com.google.gson.stream.JsonReader.nextName(JsonReader.java:789)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:215)
12-17 11:43:56.403 31885-32148/com.cajanegra.stam W/System.err: ... 16 more
This is the json that the lib is trying to parse
{
"biggest_ride_distance": null,
"biggest_climb_elevation_gain": null,
"recent_ride_totals": {
"count": 0,
"distance": 0,
"moving_time": 0,
"elapsed_time": 0,
"elevation_gain": 0,
"achievement_count": 0
},
"recent_run_totals": {
"count": 1,
"distance": 7366.60009765625,
"moving_time": 2788,
"elapsed_time": 2828,
"elevation_gain": 52.69230651855469,
"achievement_count": 0
},
"recent_swim_totals": {
"count": 0,
"distance": 0,
"moving_time": 0,
"elapsed_time": 0,
"elevation_gain": 0,
"achievement_count": 0
},
"ytd_ride_totals": {
"count": 0,
"distance": 0,
"moving_time": 0,
"elapsed_time": 0,
"elevation_gain": 0
},
"ytd_run_totals": {
"count": 1,
"distance": 7367,
"moving_time": 2788,
"elapsed_time": 2828,
"elevation_gain": 53
},
"ytd_swim_totals": {
"count": 0,
"distance": 0,
"moving_time": 0,
"elapsed_time": 0,
"elevation_gain": 0
},
"all_ride_totals": {
"count": 0,
"distance": 0,
"moving_time": 0,
"elapsed_time": 0,
"elevation_gain": 0
},
"all_run_totals": {
"count": 1,
"distance": 7367,
"moving_time": 2788,
"elapsed_time": 2828,
"elevation_gain": 53
},
"all_swim_totals": {
"count": 0,
"distance": 0,
"moving_time": 0,
"elapsed_time": 0,
"elevation_gain": 0
}
}
Please fix it. I know It is just a validation.
Is there any way to logout so that we can sign in to different account?
Hello,
The parameter "ID" in the class "Activity" is an Integer.
But it seems that the number of activity in Strava exceed Integer max value...
It should be changed to long.
Webview enters an endless loop with a progressBar after clicking "cancel" for authorization in the auth webpage of Strava
hi there,
Thank you for your work. Any plan to update this library to comply to the new Strava APIs? (see: https://developers.strava.com/docs/oauth-updates/?utm_source=strava&utm_medium=mktgemail&utm_campaign=2018_10_15_API_update)
Marco
Hi,
I plan to use the upload API for my app and I have made sure the returned token is working correctly by using curl to upload the same GPX file.
I am getting MalformedJsonException with this call to UploadAPI:
UploadStatus uploadStatus = uploadAPI.uploadFile(new File(gpxDir, filename))
.withDataType(DataType.GPX)
.withActivityType(UploadActivityType.RIDE)
.withName("test gpx")
.withDescription("")
.isPrivate(false)
.hasTrainer(false)
.isCommute(false)
.withExternalID(filename)
.execute();
Exception stack:
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:353)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: com.sweetzpot.stravazpot.common.api.exception.StravaAPIException: A network error happened contacting Strava API
at com.sweetzpot.stravazpot.common.api.StravaAPI.execute(StravaAPI.java:28)
at com.sweetzpot.stravazpot.upload.request.UploadFileRequest.execute(UploadFileRequest.java:91)
at idv.markkuo.ambitsync.MoveInfoActivity$StravaUploadAsyncTask.doInBackground(MoveInfoActivity.java:243)
at idv.markkuo.ambitsync.MoveInfoActivity$StravaUploadAsyncTask.doInBackground(MoveInfoActivity.java:223)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
... 4 more
Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $
at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1559)
at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1401)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:593)
at com.google.gson.stream.JsonReader.peek(JsonReader.java:425)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:205)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:89)
at com.sweetzpot.stravazpot.common.api.StravaAPI.execute(StravaAPI.java:26)
... 9 more
I am new to Retrofit API. I can't seem to enable the logging so I can't check what's returning from strava. Could you give me a hint? Thanks so much.
Hello,
Was trying to use your library to retrieve favorite segments with their polylines, but...
I have the following response and You can find that map does not have summary_polyline, but just polyline (strava names it full polyline). But, unfortunately Map class do not parse this field.
Question: is it possible to add it?
{"id":3579232,"resource_state":3,"name":"Martha's Chapel - East","activity_type":"Ride","distance":4316.06,"average_grade":0.6,"maximum_grade":3.8,"elevation_high":97.6,"elevation_low":71.2,"start_latlng":[35.78940027393401,-79.00851692073047],"end_latlng":[35.790341310203075,-78.96480194292963],"start_latitude":35.78940027393401,"start_longitude":-79.00851692073047,"end_latitude":35.790341310203075,"end_longitude":-78.96480194292963,"climb_category":0,"city":"Apex","state":"NC","country":"United States","private":false,"hazardous":false,"starred":true,"created_at":"2013-03-09T20:31:02Z","updated_at":"2017-07-23T08:05:38Z","total_elevation_gain":36.2302,"map":{"id":"s3579232","polyline":"wbmyEfjfaN@kLGqM@eEDcCAiKLoQA_B@aEE_BQgBMw@_@mBy@_CoA_DyBcG[q@u@wA}@cCa@oAWi@k@aB]w@uAuEkE}MaAcCw@gCcAsDsAsFa@oCU{DA{CBiDLqGDs@Fs@Js@ZgBb@aBp@qBd@s@vBeCxEcFzCoDx@mAt@yAfByDh@_B\\aBRaBDq@DaB@aEB}CH{C?eB","resource_state":3},"effort_count":24497,"athlete_count":2098,"star_count":16,"athlete_segment_stats":{"pr_elapsed_time":368,"pr_date":"2017-07-13","effort_count":15}}
Thank you,
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.