Thunkable integrating with google fit

In the Request URL type the following to get the list of Data Sources

https://www.googleapis.com/fitness/v1/users/me/dataSources

You can then choose what Data Source you want to use and then use the first URL to get the data.

i got the results now which one is the data source?

1 Like

I circled it for you

Every type of data has its own source. It seems you have selected only this scope so you are getting only one source.

thanks for circling it

and i only want to read the device steps so i selected only one scope
and how would i fetch the users’s datasource?

1 Like

Now you can use the data source ID in the original URL

https://www.googleapis.com/fitness/v1/users/me/dataSources/[[use the data source obtained from previous API call]]/datasets/1662166801000000-1662339600000000

This will extract the data of yesterday and today.

ok now will i put this url in the webapi?

https://www.googleapis.com/fitness/v1/users/me/dataSources/derived:com.google.active_minutes:com.google.android.fit:Xiaomi:Redmi%20Note%207S:1cb0a75f:top_level/datasets/1662166801000000-1662339600000000

Are you already grabbing the access token

1 Like

what?

My guess is that this api requires user authentication via. An oauth 2.0 flow. Did you set that part up yet?

1 Like

Yes, @jared this API requires OAuth2.0 to work properly.

The next step is to get OAuth2.0 client ID and Secret ID and exchange it with as Access Token to make it work.

The idea from using the Google Playground is to test and document the steps required by the API because the Playground automatically resolves an Access Token to use with the API.

1 Like

The easiest way to set this up is to direct somebody to a website where you authenticate with Google. Your need to pass along some meaningful user identifier in the process to the website. Then on the website you could authenticate with Google, get the auth code, grab the access token with the code, and then post that value to the users object on whatever database the user object lives in.

As such, this would give you access within the app to the UsERS access token at which point you could continue to refresh the top and keeping it valid indefinitely until the user revokes the token. Once you have the token and are keeping it alive when needed, you’ll be able to make all the authenticated calls that you need to,

1 Like

No, i think
But i have a auth webpage

ok i have oauth client id

ok but how to set it up
i have a login website

What you say @jared is valid but to this specific use case there is a shortcut. The service intended for this app is a Google Fit API which is a Google service and therefore you can use the Google Consent Server as the Redirect URL. There is no need to pass it through a website in this case.

1 Like

@muneer correct me if i’m wrong here. are you saying you dont need the users access token to get this info? or that the app doesnt have to authenticate as the user to grab the users info?

@lolxdyt6950as I would use Google Cloud functions to handle all the sensitive info processing

after authentication the user on my webpage and redirecting back, i’d pass the code to the following function

exports.returnAccessToken = functions.https.onRequest(async (req, res) => {
  const cors = require("cors")({origin: true});
  cors(req, res, () => {
    // your function body here - use the provided req and res from cors
    const axios = require("axios");
    const qs = require("qs");

    const data = qs.stringify({
      "code": `${req.query.code}`,
      "client_id": "",
      "client_secret": "",
      "redirect_uri": "https://jared-gibb-project-123.web.app/",
      "grant_type": "authorization_code",
    });
    const config = {
      method: "post",
      url: "https://www.googleapis.com/oauth2/v4/token",
      headers: {

        "Content-Type": "application/x-www-form-urlencoded",
      },
      data: data,
    };

    axios(config)
        .then(function(response) {
          console.log(JSON.stringify(response.data));
          res.json(response.data);
        })
        .catch(function(error) {
          console.log(error);

          res.json(error);
        });
  });
});

refresh as needed here

exports.refreshAccessToken = functions.https.onRequest(async (req, res) => {
  const cors = require("cors")({origin: true});
  cors(req, res, async () => {
    // your function body here - use the provided req and res from cors
    const axios = require("axios");
    const qs = require("qs");
    const data = qs.stringify({
      "client_id": "",
      "client_secret": "",
      "refresh_token": `${req.query.refresh_token}`,
      "grant_type": "refresh_token",
    });
    const config = {
      method: "post",
      url: "https://www.googleapis.com/oauth2/v4/token",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded",
      },
      data: data,
    };
    const response = await axios(config);
    res.json(response);
  });
});

and save the data to the user so they can do this at any time in the future

exports.saveAccessTokenToUser = functions.https.onRequest(async (req, res) => {

  const uid = req.query.uid;
  const access_token = req.query.access_token;
  const refresh_token = req.query.refresh_token;
  const cors = require("cors")({origin: true});
  cors(req, res, async () => {
    //get a referene to the database
    const db = admin.firestore();
    //get a reference to the user document
    const userRef = db.collection("users").doc(uid);
    //save the access token to the user document
    await userRef.update({
      access_token: access_token,
      refresh_token: refresh_token
    });
    res.json({message: "success"});

  })
});

and an HTML page to handle passing around the data from app to backend PLUS the authentication component
https://jared-gibb-project-123.web.app/?state=null&code=4/0AdQt8qjb-CEljf_4GL1sheE-gjL43rYwzN3n92bsw1jkYwlSG837qg0K5MIKyvTsWN1fdA&scope=email%20profile%20https://www.googleapis.com/auth/calendar%20openid%20https://www.googleapis.com/auth/userinfo.profile%20https://www.googleapis.com/auth/userinfo.email&authuser=0&prompt=consent

and the app of course to start it all of is needed. this is only an idea
https://x.thunkable.com/projects/61e4e200e0ca1b001138c8b3/3ea7620c-96d0-4249-90e2-04d53f2cd904/blocks

The real implementation is only a bit more involved here. you’d need a firebase login page or some other auth provider.

1 Like

i have a firebase login page
with google and facebook [both not setted up since its a source code and i can enable it anytime]

https://kwiply.online

its only email here

You should have them log in from the app, direct to your google auth login so you can get permissions handled. pass their uid as a state during auth. then you can pass the uid and the code to your server for processing

1 Like

ok

No. I’m just saying that instead of creating HTML page to handle codes use the Google Consent Server to do it instead. This would mean one thing less to worry about.

You will still have to do the dance of authentication and token exchange though.