Reputation: 485
I want to write a java program using the Google Fit REST API. (It's not an Android app, so I can't use the Android API.)
It seems like there is a Java Client library for the REST API - so I was thinking this would be easy.
However, I can't find any samples/examples that explain how to use the client library (just the javadoc).
I found examples about how to use the Android API - e.g. this. But it's completely different, so no use.
For other Google APIs that I have used, the Client Library comes with examples... not so in this case.
Any ideas please? Thanks.
Upvotes: 3
Views: 4028
Reputation: 43
I had to find a way of retrieving the total number of steps for today from Google Fit using the Library you describe, or more precise, I used:
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-fitness</artifactId>
<version>v1-rev22-1.22.0</version>
</dependency>
By first reading the official Google Guide on working with data sets here and a lot of try and error, I finally managed to create an example of how to retrieve all the steps for today.
*Note: As a prerequisite you will have to obtain access for the user. In order to do this you can use the same library to obtain a Credential object. This is described here *
You will need the following imports:
import com.google.api.services.fitness.Fitness;
import com.google.api.services.fitness.model.*;
import com.google.api.client.googleapis.util.Utils;
Now, to obtain steps, I first had to initialize the Fitness service:
Fitness fitness = new Fitness.Builder(
Utils.getDefaultTransport(),
Utils.getDefaultJsonFactory(),
credential //prerequisite
).build();
Afterwards, I needed to obtain an aggregated set of data. I wanted the steps to come from all the sources which synced steps in Google Fit, so I used an already existing data source for this.
Bellow is how I created the request for the data set.
AggregateRequest aggregateRequest = new AggregateRequest();
aggregateRequest.setAggregateBy(Collections.singletonList(
new AggregateBy()
.setDataSourceId("derived:com.google.step_count.delta:com.google.android.gms:estimated_steps")));
aggregateRequest.setStartTimeMillis(DateMidnight.now().getMillis());
aggregateRequest.setEndTimeMillis(DateTime.now().getMillis());
The data source id that I used will bring the whole steps which were synchronized from all the sources connected to the Google Fit account. in the given time period. (it will always bring all the steps - no delta with the previous measurements).
You are also able to create your own data source, but that is a totally different story; check nickpharris's comment for that.
Note: DateMidnight and DateTime are classes provided by the joda library.
After you created your AgregateRequest, you can execute it and parse it.
Bellow is an exemple of how I'm calculating the sum of steps.
AggregateResponse response = request.execute();
for (AggregateBucket aggregateBucket : response.getBucket()) {
for (Dataset dataset : aggregateBucket.getDataset()) {
for (DataPoint dataPoint : dataset.getPoint()) {
for (Value value : dataPoint.getValue()) {
if (value.getIntVal() != null) {
sum += value.getIntVal(); //for steps you only receive int values
}
}
}
}
}
In order to have access to this information you will need at least one of scopes found here.
I used https://www.googleapis.com/auth/fitness.activity.read
Upvotes: 0
Reputation: 485
By piecing together some information from the javadoc, the REST API documentation, and by using some of my own examples from using other Google API Java Client Libraries, I have been able to make it work more or less... Here are some code snippets:
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.fitness.Fitness;
import com.google.api.services.fitness.model.*;
Get a GoogleCredential - this library is well documented...
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
...
.build();
Create the service that is the basis for all the calls, using credential
just created...
Fitness service = new Fitness.Builder(
HTTP_TRANSPORT,
JSON_FACTORY,
credential)
.setApplicationName(APPLICATION_NAME)
.build();
Create one or more data sources for your application / device
DataSource content = new DataSource()
.setApplication(YOUR_APPLICATION)
.setType(DATA_SOURCE_RAW)
.setName(name)
.setDataType(dataType);
Fitness.Users.DataSources.Create request =
service.users().dataSources().create("me", content);
DataSource ds = request.execute();
This is an example of a dataType
that you need to use when you create your own DataSource
... This is using a standard, public metric (in this case steps) that Google exposes... see this.
private static final String DT_STEPS = "com.google.step_count.delta";
private static final DataTypeField FIELD_STEPS = new
DataTypeField().setName("steps").setFormat(FORMAT_INTEGER);
private static final List<DataTypeField> STEPS_FIELDS = Arrays.asList(
FIELD_STEPS);
public static final DataType DATA_TYPE_STEPS =
new DataType()
.setName(DT_STEPS)
.setField(STEPS_FIELDS);
Now create the actual data points, of that DataType
, using that DataSource
- in a DataSet
...
Value value = new Value().setIntVal(Integer.valueOf(steps));
List<Value> values = Arrays.asList(value);
DataPoint point = new DataPoint()
.setValue(values)
.setDataTypeName(DT_STEPS)
.setStartTimeNanos(startNS)
.setEndTimeNanos(endNS);
List<DataPoint> dataPoints = Arrays.asList(point);
String datasetId = startNS + "-" endNS;
Dataset content = new Dataset()
.setDataSourceId(dataSourceId)
.setPoint(dataPoints)
.setMinStartTimeNs(startNS)
.setMaxEndTimeNs(endNS);
Fitness.Users.DataSources.Datasets.Patch request =
service.users().dataSources().datasets().patch(
"me",
dataSourceId,
datasetId,
content);
Dataset ds = request.execute();
You still need to create a Session
and a Segment Activity DataSet
... but those follow similar structures.
Upvotes: 2
Reputation: 1
REST API = JSON formatted data sent as a response to your request.
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/* this stuff above is maven stuff, so I assume if you use javax.json from https://docs.oracle.com/javaee/7/api/javax/json/package-summary.html
it should do the same thing. */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
final String url = "http://www.someURLThatTheServerWillReponseTo/?someParams";
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
// 200 represents HTTP OK
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray data = response.optJSONArray("dataReturned");
//Here is where you decided on what to do with the data that is returned
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Upvotes: -1