[JAVA] Get account information by accessing Strava's API

Introduction

Strava has an API! But there is no Japanese document! It's hard to understand! I had a hard time in this situation, so I would like to keep a record for the athlete engineer. Let's exercise together and code with a healthy body! !!

What is Strava

This is an SNS for athletes. You can record various activities such as running, biking, and swimming. In strava, API for developersが提供されており、このAPIを使うことでアスリート情報や登録してある自転車やシューズの情報を取得できます。

Content of this article

It describes how to register the app on Strava and make an HTTP request to get the bicycle information. GET? POST? what is that? I made it from such a state, so I think that the content is easy to understand even for beginners.

Development environment

Especially this time, I think that it does not depend on the development environment, but I will describe it for the time being.

Register your app on Strava

First, log in to strava and go to the settings page under My API Application ( https://developers.strava.com/)アクセスすると自分のアプリを登録することができます。

At this point, it's okay if you don't have a separate app, so let's register appropriately. For the time being the website

http://127.0.0.1:8080

will do. : 8080 is set to 8080 because I intended to make an application using tomcat. (8080 is the port number used by tomcat.)

Authentication callback domain too

127.0.0.1:8080

I will leave it as.

スクリーンショット 2019-09-22 21.42.37.png

If you register the icon properly, the client ID, client sheet, and other values will be given. スクリーンショット 2019-09-22 21.49.00.png

Access Web API

There are two main tasks.

  1. Get the access token needed to hit the Web API.
  2. Then use the token to access the Web API and get the information.

1. Obtaining an access token

Strava has introduced a mechanism called Oauth 2.0. Regarding Oauth, the following Qiita article was very easy to understand, so please refer to this. The most easy-to-understand explanation of OAuth

Basically strava's official documentation Will be followed.

In order to get the token, add the header information to the following URL and use the GET method to skip the HTTP request.

https://www.strava.com/oauth/mobile/authorize

When adding information in the GET method, add it after the URL. The following five pieces of information are required to obtain the token this time.

  1. clientid This is the value of the client ID that was displayed when you registered the app on Strava earlier.

  2. redirect_uri Gives the URL to redirect to after authentication is complete. ** Note: The request will fail if it is not included in the domain of this redirect URL and the authentication callback domain when you registered your app on Strava ** So in this case the redirect_uri domain should also be 127.0.0.1.

  3. response_type This value is always ** code **.

  4. approval_prompt Select either ** force ** or ** auto **. ** force **: Authentication is performed every time. ** auto **: Once authenticated, it will be automatically authenticated for a while (?).

  5. scope You can decide the range of access to user information. Since various things such as ** read **, ** read_all **, ** profile: read_all ** are prepared Choose the one that suits what you want to do with your app.

As an example, the URL with the header added looks like this:

https://www.strava.com/oauth/authorize?client_id=****&response_type=code&redirect_uri=http://127.0.0.1:8080/hoge&scope=read&approval_prompt=auto

When you access this URL, you will see the following screen. スクリーンショット 2019-09-22 22.21.22.png

If you press Allow here, you will be taken to the Strava login screen, and when you log in, you will be authenticated and you will be taken to the redirect URL. I think that the URL of the redirect destination contains the part "code =".

hogehoge/state=&code=hogehogehogehoge&scope....

** Make a note of the value in this code as it will be used. ** **

Next, make an HTTP request to the following URL using the POST method.

https://www.strava.com/oauth/token

You can get an access token by giving the necessary information to the body of this POST method. The following 5 pieces of information are given to the body.

  1. clientID The value of the client ID given when you registered the app on Strava

  2. client_secret Client sheet value given when registering the app on Strava (Error in client secret?)

  3. code The value of the code included in the URL of the redirect destination earlier

  4. grant_type Be sure to use ** authorization_code **. I think that the implementation of the POST method differs depending on the environment in which the application is implemented, but in the case of Java, it was implemented in the following form.

request_token.java


    URL url = new URL("https://www.strava.com/oauth/token");
    HttpURLConnection con = (HttpURLConnection)url.openConnection();
    con.setRequestMethod("POST");
    con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    con.setDoOutput(true);
    con.setDoInput(true);
    con.connect();

    String body = "client_id=****&client_secret=****&code=****&grant_type=authorization_code";
    byte[] postData = body.getBytes(StandardCharsets.UTF_8);
    try(DataOutputStream outputStream = new DataOutputStream(con.getOutputStream())){
        outputStream.write(postData);
    }

Then, ** access_token ** exists in the response to this request, so get this token. The sample code looks like the following.

gettoken.java


    String responseData = "";
    InputStream stream = con.getInputStream();
    StringBuffer sb = new StringBuffer();
    String line = "";
    BufferedReader br = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
    while((line = br.readLine()) != null) {
        sb.append(line);
    }
    try {
        stream.close();
    }catch(Exception e) {
        e.printStackTrace();
    }
    responseData = sb.toString();
    con.disconnect();

    JSONObject json = new JSONObject(responseData);
    String token = json.getString("access_token");

2. Get information

I would like to actually get bicycle information using the access token I got earlier. In order to get the bicycle information, if you get the athlete information, it seems that it is written in it, so I will try to get the athlete information.

According to the official documentation (https://developers.strava.com/docs/reference/#api-Athletes)

https://www.strava.com/api/v3/athlete

On the other hand, it says that if you give token to the property and GET it, a response will be returned, so I will try it as told.

The sample code looks like the following. Don't forget to prefix the token with "Bearer".

getathlete.java


    url = new URL("https://www.strava.com/api/v3/athlete");
    HttpURLConnection con = (HttpURLConnection)url.openConnection();
    con.setRequestMethod("GET");
    String authorization = "Bearer " + token;  //token is the value of token obtained earlier
    con.setRequestProperty("Authorization", authorization);
    con.setDoOutput(false);
    con.setDoInput(true);
    con.connect();

    responseData = "";
    stream = con.getInputStream();
    sb = new StringBuffer();
    line = "";
    br = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
    while((line = br.readLine()) != null) {
        sb.append(line);
    }
    try {
        stream.close();
    }catch(Exception e) {
        e.printStackTrace();
    }
    responseData = sb.toString();
    con.disconnect();
    json = new JSONObject(responseData);

As you can see from the official document, the bicycle information has a nested structure of an array called bike []. In such a case, you need to get it using jsonarray etc.

getbikes.java


    JSONArray BIKE = json.getJSONArray("bikes");
    int distance = BIKE.getJSONObject(Integer.parseInt(0)).getInt("distance");
    String bikeid = BIKE.getJSONObject(Integer.parseInt(0)).getString("id");
    String bikename = BIKE.getJSONObject(Integer.parseInt(0)).getString("name");

Finally

I wrote a series of flow to get information by hitting API after registering the application on Strava. I think that it depends on the implementation environment depending on the requested part, but isn't the general flow the same? Let's use Strava's API well and exercise efficiently!

Recommended Posts

Get account information by accessing Strava's API
Get data with api created by curl command
◆ Get API created by Spring Boot from React
[Spring Boot] Get user information with Rest API (beginner)
Get Android location information
Get Android location information
Get location information in Rails and sort in ascending order
Get EXIF information in Java
[Ethereum] Get block information using web3j
Acquisition of location information using FusedLocationProviderClient
Get caller information from stack trace (java)
[Java] Get tag information from music files
Get account information by accessing Strava's API