+ * Note that, if this data point is part of a {@link DataSet}, the data source returned here may be different from the data set's data source. In case of + * transformed or merged data sets, each data point's original data source will retain the original attribution as much as possible, while the + * data set's data source will represent the merged or transformed stream. + *
+ * WARNING: do not rely on this field for anything other than debugging. The value of this field, if it is set at all, is an implementation detail and
+ * is not guaranteed to remain consistent.
+ */
+ @NonNull
+ public DataSource getOriginalDataSource() {
+ if (originalDataSource != null) return originalDataSource;
+ return dataSource;
+ }
+
+ /**
+ * Returns the start time of the interval represented by this data point, in the given unit since epoch.
+ */
+ public long getStartTime(@NonNull TimeUnit timeUnit) {
+ return timeUnit.convert(this.startTimeNanos, TimeUnit.NANOSECONDS);
+ }
+
+ /**
+ * Returns the timestamp of the data point, in the given unit since epoch. For data points that represent intervals, this method will return the
+ * end time.
+ */
+ public long getTimestamp(@NonNull TimeUnit timeUnit) {
+ return timeUnit.convert(this.timestampNanos, TimeUnit.NANOSECONDS);
+ }
+
+ /**
+ * Returns the value holder for the field with the given name. This method can be used both to query the value and to set it.
+ *
+ * @param field One of the fields of this data type.
+ * @return The Value associated with the given field.
+ * @throws IllegalArgumentException If the given field doesn't match any of the fields for this DataPoint's data type.
+ */
+ @NonNull
+ public Value getValue(com.google.android.gms.fitness.data.Field field) {
+ return this.values[getDataType().indexOf(field)];
+ }
+
+ long getTimestampNanos() {
+ return timestampNanos;
+ }
+
+ long getStartTimeNanos() {
+ return startTimeNanos;
+ }
+
+ Value[] getValues() {
+ return values;
+ }
+
+ DataSource getOriginalDataSourceIfSet() {
+ return originalDataSource;
+ }
+
+ long getRawTimestamp() {
+ return rawTimestamp;
+ }
+
+ /**
+ * Sets the values of this data point, where the format for all of its values is float.
+ *
+ * @param values The value for each field of the data point, in order.
+ * @deprecated Use {@link DataPoint.Builder} to create {@link DataPoint} instances.
+ */
+ @Deprecated
+ public DataPoint setFloatValues(float... values) {
+ if (values.length != this.getDataType().getFields().size())
+ throw new IllegalArgumentException("The number of values does not match the number of fields");
+ for (int i = 0; i < values.length; i++) {
+ this.values[i].setFloat(values[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the values of this data point, where the format for all of its values is int.
+ *
+ * @param values The value for each field of the data point, in order.
+ * @deprecated Use {@link DataPoint.Builder} to create {@link DataPoint} instances.
+ */
+ @Deprecated
+ public DataPoint setIntValues(int... values) {
+ if (values.length != this.getDataType().getFields().size())
+ throw new IllegalArgumentException("The number of values does not match the number of fields");
+ for (int i = 0; i < values.length; i++) {
+ this.values[i].setInt(values[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the time interval of a data point that represents an interval of time. For data points that represent instantaneous readings,
+ * {@link #setTimestamp(long, TimeUnit)} should be used.
+ *
+ * @param startTime The start time in the given unit, representing elapsed time since epoch.
+ * @param endTime The end time in the given unit, representing elapsed time since epoch.
+ * @param timeUnit The time unit of both start and end timestamps.
+ * @deprecated Use {@link DataPoint.Builder} to create {@link DataPoint} instances.
+ */
+ @Deprecated
+ public DataPoint setTimeInterval(long startTime, long endTime, TimeUnit timeUnit) {
+ this.startTimeNanos = timeUnit.toNanos(startTime);
+ this.timestampNanos = timeUnit.toNanos(endTime);
+ return this;
+ }
+
+ /**
+ * Sets the timestamp of a data point that represent an instantaneous reading, measurement, or input. For data points that represent intervals,
+ * {@link #setTimeInterval(long, long, TimeUnit)} should be used.
+ *
+ * @param timestamp The timestamp in the given unit, representing elapsed time since epoch.
+ * @param timeUnit The unit of the given timestamp.
+ * @deprecated Use {@link DataPoint.Builder} to create {@link DataPoint} instances.
+ */
+ @Deprecated
+ public DataPoint setTimestamp(long timestamp, TimeUnit timeUnit) {
+ this.timestampNanos = timeUnit.toNanos(timestamp);
+ return this;
+ }
+
+ /**
+ * Creates a new builder for a {@link DataPoint} with the given {@code dataSource}.
+ *
+ * @throws NullPointerException If specified data source is null.
+ */
+ @NonNull
+ public static Builder builder(@NonNull DataSource dataSource) {
+ return new Builder(dataSource);
+ }
+
+ /**
+ * Creates a new data point for the given dataSource. An unset {@link Value} is created for each field of the data source's data type.
+ *
+ * @return An empty data point instance.
+ * @deprecated Use {@link DataPoint.Builder} to create {@link DataPoint} instances.
+ */
+ @NonNull
+ @Deprecated
+ public static DataPoint create(@NonNull DataSource dataSource) {
+ return new DataPoint(dataSource);
+ }
+
+ /**
+ * Extracts a data point from a callback intent received after registering to a data source with a PendingIntent.
+ *
+ * @return The extracted DataPoint, or {@code null} if the given intent does not contain a DataPoint
+ */
+ @Nullable
+ public static DataPoint extract(@NonNull Intent intent) {
+ return SafeParcelableSerializer.deserializeFromBytes(intent.getByteArrayExtra("com.google.android.gms.fitness.EXTRA_DATA_POINT"), CREATOR);
+ }
+
+ /**
+ * Builder for {@link DataPoint} instances.
+ */
+ public static class Builder {
+ private final DataPoint dataPoint;
+ private boolean built = false;
+
+ Builder(DataSource dataSource) {
+ this.dataPoint = DataPoint.create(dataSource);
+ }
+
+ /**
+ * Builds and returns the {@link DataPoint}.
+ */
+ @NonNull
+ public DataPoint build() {
+ if (built) throw new IllegalStateException("DataPoint already built");
+ this.built = true;
+ return this.dataPoint;
+ }
+
+ /**
+ * Sets the value of an activity field to {@code activity}.
+ *
+ * @throws IllegalArgumentException If the given index is out of the range for this data type.
+ * @throws IllegalStateException If the field isn't of format {@link com.google.android.gms.fitness.data.Field#FORMAT_INT32}.
+ */
+ @NonNull
+ public Builder setActivityField(@NonNull com.google.android.gms.fitness.data.Field field, @NonNull String activity) {
+ if (built) throw new IllegalStateException("DataPoint already built");
+ this.dataPoint.getValue(field).setActivity(activity);
+ return this;
+ }
+
+ /**
+ * Sets the floating point value of the given {@code field} to {@code value}.
+ *
+ * @throws IllegalArgumentException If the given index is out of the range for this data type.
+ * @throws IllegalStateException If the field isn't of format {@link com.google.android.gms.fitness.data.Field#FORMAT_FLOAT}.
+ */
+ @NonNull
+ public Builder setField(@NonNull com.google.android.gms.fitness.data.Field field, float value) {
+ if (built) throw new IllegalStateException("DataPoint already built");
+ this.dataPoint.getValue(field).setFloat(value);
+ return this;
+ }
+
+
+ /**
+ * Sets the map value of the given {@code field} to {@code value}.
+ *
+ * @throws IllegalArgumentException If the given index is out of the range for this data type.
+ * @throws IllegalStateException If the field isn't of format {@link com.google.android.gms.fitness.data.Field#FORMAT_MAP}.
+ */
+ @NonNull
+ public Builder setField(@NonNull com.google.android.gms.fitness.data.Field field, @NonNull Map
+ * Certain APIs that return a DataSet might insert data points in chronological order, but this isn't enforced.
+ */
+ @NonNull
+ public List
+ * Data points with the matching data source can be created using {@link #createDataPoint()}, and after having the values set added to the data set
+ * via {@link #add(DataPoint)}.
+ *
+ * @throws NullPointerException If specified data source is null.
+ */
+ @NonNull
+ public static DataSet create(@NonNull DataSource dataSource) {
+ return new DataSet(dataSource);
+ }
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
+ /**
+ * Builder used to create new data sets.
+ */
+ public static class Builder {
+ private final DataSet dataSet;
+ private boolean built = false;
+
+ Builder(DataSource dataSource) {
+ this.dataSet = DataSet.create(dataSource);
+ }
+
+ /**
+ * Adds a data point to this data set. The data points should be for the correct data type and data source, and should have its timestamp
+ * already set.
+ *
+ * @throws IllegalArgumentException If dataPoint has the wrong {@link DataSource}, or contain invalid data.
+ */
+ @NonNull
+ public Builder add(@NonNull DataPoint dataPoint) {
+ if (built) throw new IllegalStateException("DataSet has already been built.");
+ this.dataSet.add(dataPoint);
+ return this;
+ }
+
+ /**
+ * Adds a list of data points to this data set in bulk. All data points should be for the correct data type and data source, and should have their
+ * timestamp already set.
+ *
+ * @throws IllegalArgumentException If the {@code dataPoints} have the wrong source, or contain invalid data.
+ */
+ @NonNull
+ public Builder addAll(@NonNull Iterable
+ * The data source contains enough information to uniquely identify its data, including the hardware device and the application that
+ * collected and/or transformed the data. It also holds useful metadata, such as a stream name and the device type.
+ *
+ * The data source's data stream can be accessed in a live fashion by registering a data source listener, or via queries over fixed time intervals.
+ *
+ * An end-user-visible name for the data stream can be set by calling {@link DataSource.Builder.setStreamName(String)} or otherwise computed
+ * from the device model and application name.
+ */
@SafeParcelable.Class
public class DataSource extends AbstractSafeParcelable {
- @Field(1)
- public DataType dataType;
- @Field(3)
- public int type;
- @Field(4)
- public Device device;
- @Field(5)
- public AppInfo appInfo;
- @Field(6)
- public String info;
+ /**
+ * Name for the parcelable intent extra containing a data source. It can be extracted using {@link #extract(Intent)}.
+ */
+ public static final String EXTRA_DATA_SOURCE = "vnd.google.fitness.data_source";
+
+ /**
+ * Type constant for a data source which exposes original, raw data from an external source such as a hardware sensor, a wearable device, or
+ * user input.
+ */
+ public static final int TYPE_RAW = 0;
+
+ /**
+ * Type constant for a data source which exposes data which is derived from one or more existing data sources by performing
+ * transformations on the original data.
+ */
+ public static final int TYPE_DERIVED = 1;
+
+ @Field(value = 1, getterName = "getDataType")
+ @NonNull
+ private final DataType dataType;
+ @Field(value = 3, getterName = "getType")
+ private final int type;
+ @Field(value = 4, getterName = "getDevice")
+ @Nullable
+ private final Device device;
+ @Field(value = 5, getterName = "getApplication")
+ @Nullable
+ final Application application;
+ @Field(value = 6, getterName = "getStreamName")
+ private final String streamName;
+
+ @Constructor
+ DataSource(@Param(1) @NonNull DataType dataType, @Param(3) int type, @Param(4) @Nullable Device device, @Param(5) @Nullable Application application, @Param(6) String streamName) {
+ this.dataType = dataType;
+ this.type = type;
+ this.device = device;
+ this.application = application;
+ this.streamName = streamName;
+ }
+
+ @Nullable
+ public Application getApplication() {
+ return application;
+ }
+
+ /**
+ * Returns the package name for the application responsible for setting the data, or {@code null} if unset/unknown. {@link PackageManager} can be used to
+ * query relevant information about the application, such as the name, icon, and logo.
+ *
+ * Data coming from local sensors or BLE devices will not have a corresponding application.
+ */
+ @Nullable
+ public String getAppPackageName() {
+ if (application == null) return null;
+ return application.getPackageName();
+ }
+
+ /**
+ * Returns the data type for data coming from this data source. Knowing the type of a data source can be useful to perform transformations on
+ * top of raw data without using sources that are themselves computed by transforming raw data.
+ */
+ @NonNull
+ public DataType getDataType() {
+ return dataType;
+ }
+
+ /**
+ * Returns the device where data is being collected, or {@code null} if unset.
+ */
+ @Nullable
+ public Device getDevice() {
+ return device;
+ }
+
+ /**
+ * Returns a unique identifier for the data stream produced by this data source. The identifier includes, in order:
+ *
+ * Note that it may be useful to set the device even if the data is not coming from a hardware sensor on the device. For instance, if the user
+ * installs an application which generates sensor data in two separate devices, the only way to differentiate the two data sources is using the
+ * device. This can be specially important if both devices are used at the same time.
+ */
+ @NonNull
+ public Builder setDevice(@NonNull Device device) {
+ this.device = device;
+ return this;
+ }
+
+ /**
+ * The stream name uniquely identifies this particular data source among other data sources of the same type from the same underlying
+ * producer. Setting the stream name is optional, but should be done whenever an application exposes two streams for the same data type, or
+ * when a device has two equivalent sensors.
+ *
+ * The stream name is used by {@link DataSource#getStreamIdentifier()} to make sure the different streams are properly separated when
+ * querying or persisting data.
+ *
+ * @throws IllegalArgumentException If the specified stream name is null.
+ */
+ @NonNull
+ public Builder setStreamName(@NonNull String streamName) {
+ //noinspection ConstantValue
+ if (streamName == null) throw new IllegalArgumentException("streamName must be set");
+ this.streamName = streamName;
+ return this;
+ }
+
+ /**
+ * Sets the type of the data source. {@link DataSource#TYPE_DERIVED} should be used if any other data source is used in generating the data.
+ * {@link DataSource#TYPE_RAW} should be used if the data comes completely from outside of Google Fit.
+ */
+ @NonNull
+ public Builder setType(int type) {
+ this.type = type;
+ return this;
+ }
+ }
+
public static final SafeParcelableCreatorAndWriter
+ * A data type contains one or more fields. In case of multi-dimensional data (such as location with latitude, longitude, and accuracy) each
+ * field represents one dimension. Each data type field has a unique name which identifies it. The field also defines the format of the data
+ * (such as int or float).
+ *
+ * The data types in the {@code com.google} namespace are shared with any app with the user consent. These are fixed and can only be updated in
+ * new releases of the platform. This class contains constants representing each of the {@code com.google} data types, each prefixed with {@code TYPE_}.
+ * Custom data types can be accessed via the {@link ConfigClient}.
+ *
+ * Certain data types can represent aggregates, and can be computed as part of read requests by calling
+ * {@link DataReadRequest.Builder#aggregate(DataType)}. This class contains constants for all the valid aggregates, each prefixed with
+ * {@code AGGREGATE_}. The aggregates for each input type can be queried via {@link #getAggregatesForInput(DataType)}.
+ */
@SafeParcelable.Class
public class DataType extends AbstractSafeParcelable {
+ /**
+ * The common prefix for data type MIME types, for use in intents. The MIME type for a particular data type will be this prefix followed by
+ * the data type name.
+ *
+ * The data type's name is returned by {@link #getName()}. The full MIME type can be computed by {@link #getMimeType(DataType)}.
+ */
+ public static final String MIME_TYPE_PREFIX = "vnd.google.fitness.data_type/";
- public static final DataType TYPE_STEP_COUNT_DELTA = new DataType("com.google.step_count.delta", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_STEPS);
- public static final DataType TYPE_STEP_COUNT_CUMULATIVE = new DataType("com.google.step_count.cumulative", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_STEPS);
- public static final DataType TYPE_STEP_COUNT_CADENCE = new DataType("com.google.step_count.cadence", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_RPM);
- public static final DataType TYPE_INTERNAL_GOAL = new DataType("com.google.internal.goal", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_FITNESS_GOAL_V2);
- public static final DataType TYPE_ACTIVITY_SEGMENT = new DataType("com.google.activity.segment", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_ACTIVITY);
- public static final DataType TYPE_SLEEP_SEGMENT = new DataType("com.google.sleep.segment", "https://www.googleapis.com/auth/fitness.sleep.read", "https://www.googleapis.com/auth/fitness.sleep.write", com.google.android.gms.fitness.data.Field.FIELD_SLEEP_SEGMENT_TYPE);
- public static final DataType TYPE_CALORIES_EXPENDED = new DataType("com.google.calories.expended", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_CALORIES);
- public static final DataType TYPE_BASAL_METABOLIC_RATE = new DataType("com.google.calories.bmr", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_CALORIES);
- public static final DataType TYPE_POWER_SAMPLE = new DataType("com.google.power.sample", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_WATTS);
- public static final DataType TYPE_SENSOR_EVENTS = new DataType("com.google.sensor.events", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_SENSOR_TYPE, com.google.android.gms.fitness.data.Field.FIELD_TIMESTAMPS, com.google.android.gms.fitness.data.Field.FIELD_SENSOR_VALUES);
- public static final DataType TYPE_HEART_RATE_BPM = new DataType("com.google.heart_rate.bpm", "https://www.googleapis.com/auth/fitness.heart_rate.read", "https://www.googleapis.com/auth/fitness.heart_rate.write", com.google.android.gms.fitness.data.Field.FIELD_BPM);
- public static final DataType TYPE_RESPIRATORY_RATE = new DataType("com.google.respiratory_rate", "https://www.googleapis.com/auth/fitness.respiratory_rate.read", "https://www.googleapis.com/auth/fitness.respiratory_rate.write", com.google.android.gms.fitness.data.Field.FIELD_RESPIRATORY_RATE);
- public static final DataType TYPE_LOCATION_SAMPLE = new DataType("com.google.location.sample", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_LATITUDE, com.google.android.gms.fitness.data.Field.FIELD_LONGITUDE, com.google.android.gms.fitness.data.Field.FIELD_ACCURACY, com.google.android.gms.fitness.data.Field.FIELD_ALTITUDE);
+ public static final DataType TYPE_ACTIVITY_SEGMENT = new DataType("com.google.activity.segment", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_ACTIVITY);
+ public static final DataType TYPE_BASAL_METABOLIC_RATE = new DataType("com.google.calories.bmr", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_CALORIES);
+ public static final DataType TYPE_BODY_FAT_PERCENTAGE = new DataType("com.google.body.fat.percentage", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", FIELD_PERCENTAGE);
+ public static final DataType TYPE_CALORIES_EXPENDED = new DataType("com.google.calories.expended", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_CALORIES);
+ public static final DataType TYPE_CYCLING_PEDALING_CADENCE = new DataType("com.google.cycling.pedaling.cadence", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_RPM);
+ public static final DataType TYPE_CYCLING_PEDALING_CUMULATIVE = new DataType("com.google.cycling.pedaling.cumulative", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_REVOLUTIONS);
+ public static final DataType TYPE_CYCLING_WHEEL_REVOLUTION = new DataType("com.google.cycling.wheel_revolution.cumulative", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_REVOLUTIONS);
+ public static final DataType TYPE_CYCLING_WHEEL_RPM = new DataType("com.google.cycling.wheel_revolution.rpm", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_RPM);
+ public static final DataType TYPE_DISTANCE_DELTA = new DataType("com.google.distance.delta", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_DISTANCE);
+ public static final DataType TYPE_HEART_POINTS = new DataType("com.google.heart_minutes", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_INTENSITY);
+ public static final DataType TYPE_HEART_RATE_BPM = new DataType("com.google.heart_rate.bpm", "https://www.googleapis.com/auth/fitness.heart_rate.read", "https://www.googleapis.com/auth/fitness.heart_rate.write", FIELD_BPM);
+ public static final DataType TYPE_HEIGHT = new DataType("com.google.height", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", FIELD_HEIGHT);
+ public static final DataType TYPE_HYDRATION = new DataType("com.google.hydration", "https://www.googleapis.com/auth/fitness.nutrition.read", "https://www.googleapis.com/auth/fitness.nutrition.write", FIELD_VOLUME);
+ public static final DataType TYPE_LOCATION_SAMPLE = new DataType("com.google.location.sample", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_LATITUDE, FIELD_LONGITUDE, FIELD_ACCURACY, FIELD_ALTITUDE);
@Deprecated
- public static final DataType TYPE_LOCATION_TRACK = new DataType("com.google.location.track", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_LATITUDE, com.google.android.gms.fitness.data.Field.FIELD_LONGITUDE, com.google.android.gms.fitness.data.Field.FIELD_ACCURACY, com.google.android.gms.fitness.data.Field.FIELD_ALTITUDE);
- public static final DataType TYPE_DISTANCE_DELTA = new DataType("com.google.distance.delta", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_DISTANCE);
- public static final DataType TYPE_SPEED = new DataType("com.google.speed", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_SPEED);
- public static final DataType TYPE_CYCLING_WHEEL_REVOLUTION = new DataType("com.google.cycling.wheel_revolution.cumulative", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_REVOLUTIONS);
- public static final DataType TYPE_CYCLING_WHEEL_RPM = new DataType("com.google.cycling.wheel_revolution.rpm", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_RPM);
- public static final DataType TYPE_CYCLING_PEDALING_CUMULATIVE = new DataType("com.google.cycling.pedaling.cumulative", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_REVOLUTIONS);
- public static final DataType TYPE_CYCLING_PEDALING_CADENCE = new DataType("com.google.cycling.pedaling.cadence", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_RPM);
- public static final DataType TYPE_HEIGHT = new DataType("com.google.height", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", com.google.android.gms.fitness.data.Field.FIELD_HEIGHT);
- public static final DataType TYPE_WEIGHT = new DataType("com.google.weight", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", com.google.android.gms.fitness.data.Field.FIELD_WEIGHT);
- public static final DataType TYPE_BODY_FAT_PERCENTAGE = new DataType("com.google.body.fat.percentage", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", com.google.android.gms.fitness.data.Field.FIELD_PERCENTAGE);
- public static final DataType TYPE_NUTRITION = new DataType("com.google.nutrition", "https://www.googleapis.com/auth/fitness.nutrition.read", "https://www.googleapis.com/auth/fitness.nutrition.write", com.google.android.gms.fitness.data.Field.FIELD_NUTRIENTS, com.google.android.gms.fitness.data.Field.FIELD_MEAL_TYPE, com.google.android.gms.fitness.data.Field.FIELD_FOOD_ITEM);
- public static final DataType AGGREGATE_HYDRATION = new DataType("com.google.hydration", "https://www.googleapis.com/auth/fitness.nutrition.read", "https://www.googleapis.com/auth/fitness.nutrition.write", com.google.android.gms.fitness.data.Field.FIELD_VOLUME);
- public static final DataType TYPE_WORKOUT_EXERCISE = new DataType("com.google.activity.exercise", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_EXERCISE, com.google.android.gms.fitness.data.Field.FIELD_REPETITIONS, com.google.android.gms.fitness.data.Field.FIELD_DURATION_OPTIONAL, com.google.android.gms.fitness.data.Field.FIELD_RESISTANCE_TYPE, com.google.android.gms.fitness.data.Field.FIELD_RESISTANCE);
- public static final DataType TYPE_MOVE_MINUTES = new DataType("com.google.active_minutes", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_DURATION);
+ public static final DataType TYPE_LOCATION_TRACK = new DataType("com.google.location.track", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_LATITUDE, FIELD_LONGITUDE, FIELD_ACCURACY, FIELD_ALTITUDE);
+ public static final DataType TYPE_MOVE_MINUTES = new DataType("com.google.active_minutes", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_DURATION);
+ public static final DataType TYPE_NUTRITION = new DataType("com.google.nutrition", "https://www.googleapis.com/auth/fitness.nutrition.read", "https://www.googleapis.com/auth/fitness.nutrition.write", FIELD_NUTRIENTS, FIELD_MEAL_TYPE, FIELD_FOOD_ITEM);
+ public static final DataType TYPE_POWER_SAMPLE = new DataType("com.google.power.sample", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_WATTS);
+ public static final DataType TYPE_SLEEP_SEGMENT = new DataType("com.google.sleep.segment", "https://www.googleapis.com/auth/fitness.sleep.read", "https://www.googleapis.com/auth/fitness.sleep.write", FIELD_SLEEP_SEGMENT_TYPE);
+ public static final DataType TYPE_SPEED = new DataType("com.google.speed", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_SPEED);
+ public static final DataType TYPE_STEP_COUNT_CADENCE = new DataType("com.google.step_count.cadence", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_RPM);
+ public static final DataType TYPE_STEP_COUNT_DELTA = new DataType("com.google.step_count.delta", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_STEPS);
+ public static final DataType TYPE_WEIGHT = new DataType("com.google.weight", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", FIELD_WEIGHT);
+ public static final DataType TYPE_WORKOUT_EXERCISE = new DataType("com.google.activity.exercise", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_EXERCISE, FIELD_REPETITIONS, FIELD_DURATION_OPTIONAL, FIELD_RESISTANCE_TYPE, FIELD_RESISTANCE);
+
+ public static final DataType TYPE_DEVICE_ON_BODY = new DataType("com.google.device_on_body", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_PROBABILITY);
+ public static final DataType TYPE_INTERNAL_GOAL = new DataType("com.google.internal.goal", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_FITNESS_GOAL_V2);
+ public static final DataType TYPE_MET = new DataType("com.google.internal.met", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_MET);
+ public static final DataType TYPE_PACED_WALKING_ATTRIBUTES = new DataType("com.google.internal.paced_walking_attributes", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_FITNESS_PACED_WALKING_ATTRIBUTES);
+ public static final DataType TYPE_RESPIRATORY_RATE = new DataType("com.google.respiratory_rate", "https://www.googleapis.com/auth/fitness.respiratory_rate.read", "https://www.googleapis.com/auth/fitness.respiratory_rate.write", FIELD_RESPIRATORY_RATE);
+ public static final DataType TYPE_SENSOR_EVENTS = new DataType("com.google.sensor.events", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_SENSOR_TYPE, FIELD_TIMESTAMPS, FIELD_SENSOR_VALUES);
+ public static final DataType TYPE_SLEEP_ATTRIBUTES = new DataType("com.google.internal.sleep_attributes", "https://www.googleapis.com/auth/fitness.sleep.read", "https://www.googleapis.com/auth/fitness.sleep.write", FIELD_FITNESS_SLEEP_ATTRIBUTES);
+ public static final DataType TYPE_SLEEP_SCHEDULE = new DataType("com.google.internal.sleep_schedule", "https://www.googleapis.com/auth/fitness.sleep.read", "https://www.googleapis.com/auth/fitness.sleep.write", FIELD_FITNESS_SLEEP_SCHEDULE);
+ public static final DataType TYPE_STEP_COUNT_CUMULATIVE = new DataType("com.google.step_count.cumulative", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_STEPS);
+ public static final DataType TYPE_TIME_ZONE_CHANGE = new DataType("com.google.time_zone_change", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_ZONE_ID);
+ public static final DataType TYPE_WORKOUT_SAMPLES = new DataType("com.google.activity.samples", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_ACTIVITY_CONFIDENCE);
+
+
+ public static final DataType AGGREGATE_ACTIVITY_SUMMARY = new DataType("com.google.activity.summary", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_ACTIVITY, FIELD_DURATION, FIELD_NUM_SEGMENTS);
+ public static final DataType AGGREGATE_BASAL_METABOLIC_RATE_SUMMARY = new DataType("com.google.calories.bmr.summary", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_AVERAGE, FIELD_MAX, FIELD_MIN);
+ public static final DataType AGGREGATE_BODY_FAT_PERCENTAGE_SUMMARY = new DataType("com.google.body.fat.percentage.summary", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", FIELD_AVERAGE, FIELD_MAX, FIELD_MIN);
+ public static final DataType AGGREGATE_CALORIES_EXPENDED = TYPE_CALORIES_EXPENDED;
+ public static final DataType AGGREGATE_DISTANCE_DELTA = TYPE_DISTANCE_DELTA;
+ public static final DataType AGGREGATE_HEART_POINTS = new DataType("com.google.heart_minutes.summary", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_INTENSITY, FIELD_DURATION);
+ public static final DataType AGGREGATE_HEART_RATE_SUMMARY = new DataType("com.google.heart_rate.summary", "https://www.googleapis.com/auth/fitness.heart_rate.read", "https://www.googleapis.com/auth/fitness.heart_rate.write", FIELD_AVERAGE, FIELD_MAX, FIELD_MIN);
+ public static final DataType AGGREGATE_HEIGHT_SUMMARY = new DataType("com.google.height.summary", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", FIELD_AVERAGE, FIELD_MAX, FIELD_MIN);
+ public static final DataType AGGREGATE_HYDRATION = TYPE_HYDRATION;
+ public static final DataType AGGREGATE_LOCATION_BOUNDING_BOX = new DataType("com.google.location.bounding_box", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_LOW_LATITUDE, FIELD_LOW_LONGITUDE, FIELD_HIGH_LATITUDE, FIELD_HIGH_LONGITUDE);
public static final DataType AGGREGATE_MOVE_MINUTES = TYPE_MOVE_MINUTES;
- public static final DataType TYPE_DEVICE_ON_BODY = new DataType("com.google.device_on_body", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_PROBABILITY);
- public static final DataType AGGREGATE_ACTIVITY_SUMMARY = new DataType("com.google.activity.summary", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_ACTIVITY, com.google.android.gms.fitness.data.Field.FIELD_DURATION, com.google.android.gms.fitness.data.Field.FIELD_NUM_SEGMENTS);
- public static final DataType AGGREGATE_BASAL_METABOLIC_RATE_SUMMARY = new DataType("com.google.calories.bmr.summary", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_AVERAGE, com.google.android.gms.fitness.data.Field.FIELD_MAX, com.google.android.gms.fitness.data.Field.FIELD_MIN);
+ public static final DataType AGGREGATE_NUTRITION_SUMMARY = new DataType("com.google.nutrition.summary", "https://www.googleapis.com/auth/fitness.nutrition.read", "https://www.googleapis.com/auth/fitness.nutrition.write", FIELD_NUTRIENTS, FIELD_MEAL_TYPE);
+ public static final DataType AGGREGATE_POWER_SUMMARY = new DataType("com.google.power.summary", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", FIELD_AVERAGE, FIELD_MAX, FIELD_MIN);
+ public static final DataType AGGREGATE_SPEED_SUMMARY = new DataType("com.google.speed.summary", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", FIELD_AVERAGE, FIELD_MAX, FIELD_MIN);
public static final DataType AGGREGATE_STEP_COUNT_DELTA = TYPE_STEP_COUNT_DELTA;
- public static final DataType AGGREGATE_DISTANCE_DELTA = TYPE_DISTANCE_DELTA;
- public static final DataType AGGREGATE_CALORIES_EXPENDED = TYPE_CALORIES_EXPENDED;
- public static final DataType TYPE_HEART_POINTS = new DataType("com.google.heart_minutes", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_INTENSITY);
- public static final DataType AGGREGATE_HEART_POINTS = new DataType("com.google.heart_minutes.summary", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_INTENSITY, com.google.android.gms.fitness.data.Field.FIELD_DURATION);
- public static final DataType AGGREGATE_HEART_RATE_SUMMARY = new DataType("com.google.heart_rate.summary", "https://www.googleapis.com/auth/fitness.heart_rate.read", "https://www.googleapis.com/auth/fitness.heart_rate.write", com.google.android.gms.fitness.data.Field.FIELD_AVERAGE, com.google.android.gms.fitness.data.Field.FIELD_MAX, com.google.android.gms.fitness.data.Field.FIELD_MIN);
- public static final DataType AGGREGATE_LOCATION_BOUNDING_BOX = new DataType("com.google.location.bounding_box", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_LOW_LATITUDE, com.google.android.gms.fitness.data.Field.FIELD_LOW_LONGITUDE, com.google.android.gms.fitness.data.Field.FIELD_HIGH_LATITUDE, com.google.android.gms.fitness.data.Field.FIELD_HIGH_LONGITUDE);
- public static final DataType AGGREGATE_POWER_SUMMARY = new DataType("com.google.power.summary", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_AVERAGE, com.google.android.gms.fitness.data.Field.FIELD_MAX, com.google.android.gms.fitness.data.Field.FIELD_MIN);
- public static final DataType AGGREGATE_SPEED_SUMMARY = new DataType("com.google.speed.summary", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_AVERAGE, com.google.android.gms.fitness.data.Field.FIELD_MAX, com.google.android.gms.fitness.data.Field.FIELD_MIN);
- public static final DataType AGGREGATE_BODY_FAT_PERCENTAGE_SUMMARY = new DataType("com.google.body.fat.percentage.summary", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", com.google.android.gms.fitness.data.Field.FIELD_AVERAGE, com.google.android.gms.fitness.data.Field.FIELD_MAX, com.google.android.gms.fitness.data.Field.FIELD_MIN);
- public static final DataType AGGREGATE_WEIGHT_SUMMARY = new DataType("com.google.weight.summary", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", com.google.android.gms.fitness.data.Field.FIELD_AVERAGE, com.google.android.gms.fitness.data.Field.FIELD_MAX, com.google.android.gms.fitness.data.Field.FIELD_MIN);
- public static final DataType AGGREGATE_HEIGHT_SUMMARY = new DataType("com.google.height.summary", "https://www.googleapis.com/auth/fitness.body.read", "https://www.googleapis.com/auth/fitness.body.write", com.google.android.gms.fitness.data.Field.FIELD_AVERAGE, com.google.android.gms.fitness.data.Field.FIELD_MAX, com.google.android.gms.fitness.data.Field.FIELD_MIN);
- public static final DataType AGGREGATE_NUTRITION_SUMMARY = new DataType("com.google.nutrition.summary", "https://www.googleapis.com/auth/fitness.nutrition.read", "https://www.googleapis.com/auth/fitness.nutrition.write", com.google.android.gms.fitness.data.Field.FIELD_NUTRIENTS, com.google.android.gms.fitness.data.Field.FIELD_MEAL_TYPE);
- public static final DataType TYPE_HYDRATION = AGGREGATE_HYDRATION;
- public static final DataType TYPE_WORKOUT_SAMPLES = new DataType("com.google.activity.samples", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_ACTIVITY_CONFIDENCE);
- public static final DataType TYPE_SLEEP_ATTRIBUTES = new DataType("com.google.internal.sleep_attributes", "https://www.googleapis.com/auth/fitness.sleep.read", "https://www.googleapis.com/auth/fitness.sleep.write", com.google.android.gms.fitness.data.Field.FIELD_FITNESS_SLEEP_ATTRIBUTES);
- public static final DataType TYPE_SLEEP_SCHEDULE = new DataType("com.google.internal.sleep_schedule", "https://www.googleapis.com/auth/fitness.sleep.read", "https://www.googleapis.com/auth/fitness.sleep.write", com.google.android.gms.fitness.data.Field.FIELD_FITNESS_SLEEP_SCHEDULE);
- public static final DataType TYPE_PACED_WALKING_ATTRIBUTES = new DataType("com.google.internal.paced_walking_attributes", "https://www.googleapis.com/auth/fitness.activity.read", "https://www.googleapis.com/auth/fitness.activity.write", com.google.android.gms.fitness.data.Field.FIELD_FITNESS_PACED_WALKING_ATTRIBUTES);
- public static final DataType TYPE_TIME_ZONE_CHANGE = new DataType("com.google.time_zone_change", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_ZONE_ID);
- public static final DataType TYPE_MET = new DataType("com.google.internal.met", "https://www.googleapis.com/auth/fitness.location.read", "https://www.googleapis.com/auth/fitness.location.write", com.google.android.gms.fitness.data.Field.FIELD_MET);
-
- @Field(1)
- public String packageName;
- @Field(2)
- public List
+ * To check if a data type is supported for aggregation, check that the returned type is non-null.
+ */
+ @Nullable
+ public DataType getAggregateType() {
+ // TODO
+ return null;
+ }
+
+ /**
+ * Returns the ordered list of fields for the data type.
+ */
+ @NonNull
+ public List
+ * To check if a data type is supported for aggregation, check that the returned list is not empty
+ * {@code DataType.getAggregatesForInput(dataType).isEmpty()}.
+ *
+ * @deprecated Use {@link #getAggregateType()} instead.
+ */
+ @NonNull
+ @Deprecated
+ public static List
+ * Device UIDs are obfuscated based on the calling application's package name. Different applications will see different UIDs for the same
+ * {@link Device}. If two {@link Device} instances have the same underlying UID, they'll also have the same obfuscated UID within each app (but not across
+ * apps).
+ */
+ @NonNull
+ public String getUid() {
+ return uid;
+ }
+
+ String getDeviceId() {
+ return manufacturer + ":" + model + ":" + uid;
+ }
+
+ int getPlatformType() {
+ return platformType;
+ }
+
+ /**
+ * Returns the Device representation of the local device, which can be used when defining local data sources.
+ *
+ * @noinspection deprecation
+ */
+ public static Device getLocalDevice(Context context) {
+ @SuppressLint("HardwareIds") String uid = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
+ int type = TYPE_PHONE;
+ Configuration configuration = context.getResources().getConfiguration();
+ PackageManager packageManager = context.getPackageManager();
+ if (SDK_INT >= 20 && packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH))
+ type = TYPE_WATCH;
+ else if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION) || packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+ type = TYPE_UNKNOWN; // TV
+ else if (packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
+ type = TYPE_UNKNOWN; // Car
+ else if ((configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) > Configuration.SCREENLAYOUT_SIZE_LARGE && configuration.smallestScreenWidthDp >= 600)
+ type = TYPE_TABLET;
+ else if (Build.PRODUCT.startsWith("glass_"))
+ type = TYPE_HEAD_MOUNTED;
+ return new Device(Build.MANUFACTURER, Build.MODEL, uid, type, 2);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return ToStringHelper.name("Device").value(getDeviceId() + ":" + type + ":" + platformType).end();
+ }
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
diff --git a/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/Field.java b/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/Field.java
index a8b951a1d6..3971ecce5e 100644
--- a/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/Field.java
+++ b/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/Field.java
@@ -1,6 +1,9 @@
/*
* SPDX-FileCopyrightText: 2023 microG Project Team
* SPDX-License-Identifier: Apache-2.0
+ * Notice: Portions of this file are reproduced from work created and shared by Google and used
+ * according to terms described in the Creative Commons 4.0 Attribution License.
+ * See https://developers.google.com/readme/policies for details.
*/
package com.google.android.gms.fitness.data;
@@ -9,136 +12,471 @@
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
+import org.microg.gms.common.Hide;
+/**
+ * A field represents one dimension of a data type. It defines the name and format of data. Unlike data type names, field names are not
+ * namespaced, and only need to be unique within the data type.
+ *
+ * This class contains constants representing the field names of common data types, each prefixed with {@code FIELD_}. These can be used to
+ * access and set the fields via {@link DataPoint#getValue(com.google.android.gms.fitness.data.Field)}.
+ *
+ * Fields for custom data types can be created using {@link DataTypeCreateRequest.Builder#addField(String, int)}.
+ */
@SafeParcelable.Class
public class Field extends AbstractSafeParcelable {
- public static final com.google.android.gms.fitness.data.Field FIELD_ACTIVITY = formatIntField("activity");
- public static final com.google.android.gms.fitness.data.Field FIELD_SLEEP_SEGMENT_TYPE = formatIntField("sleep_segment_type");
- public static final com.google.android.gms.fitness.data.Field FIELD_CONFIDENCE = formatFloatField("confidence");
- public static final com.google.android.gms.fitness.data.Field FIELD_STEPS = formatIntField("steps");
- @Deprecated
- public static final com.google.android.gms.fitness.data.Field FIELD_STEP_LENGTH = formatFloatField("step_length");
- public static final com.google.android.gms.fitness.data.Field FIELD_DURATION = formatIntField("duration");
- public static final com.google.android.gms.fitness.data.Field FIELD_DURATION_OPTIONAL = formatIntOptionalField("duration");
- public static final com.google.android.gms.fitness.data.Field FIELD_ACTIVITY_DURATION_ASCENDING = formatMapField("activity_duration.ascending");
- public static final com.google.android.gms.fitness.data.Field FIELD_ACTIVITY_DURATION_DESCENDING = formatMapField("activity_duration.descending");
- public static final com.google.android.gms.fitness.data.Field FIELD_BPM = formatFloatField("bpm");
- public static final com.google.android.gms.fitness.data.Field FIELD_RESPIRATORY_RATE = formatFloatField("respiratory_rate");
- public static final com.google.android.gms.fitness.data.Field FIELD_LATITUDE = formatFloatField("latitude");
- public static final com.google.android.gms.fitness.data.Field FIELD_LONGITUDE = formatFloatField("longitude");
- public static final com.google.android.gms.fitness.data.Field FIELD_ACCURACY = formatFloatField("accuracy");
- public static final com.google.android.gms.fitness.data.Field FIELD_ALTITUDE = formatFloatOptionalField("altitude");
- public static final com.google.android.gms.fitness.data.Field FIELD_DISTANCE = formatFloatField("distance");
- public static final com.google.android.gms.fitness.data.Field FIELD_HEIGHT = formatFloatField("height");
- public static final com.google.android.gms.fitness.data.Field FIELD_WEIGHT = formatFloatField("weight");
- public static final com.google.android.gms.fitness.data.Field FIELD_PERCENTAGE = formatFloatField("percentage");
- public static final com.google.android.gms.fitness.data.Field FIELD_SPEED = formatFloatField("speed");
- public static final com.google.android.gms.fitness.data.Field FIELD_RPM = formatFloatField("rpm");
- public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_GOAL_V2 = formatObjectField("google.android.fitness.GoalV2");
- public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_DEVICE = formatObjectField("google.android.fitness.Device");
- public static final com.google.android.gms.fitness.data.Field FIELD_REVOLUTIONS = formatIntField("revolutions");
- public static final com.google.android.gms.fitness.data.Field FIELD_CALORIES = formatFloatField("calories");
- public static final com.google.android.gms.fitness.data.Field FIELD_WATTS = formatFloatField("watts");
- public static final com.google.android.gms.fitness.data.Field FIELD_VOLUME = formatFloatField("volume");
- public static final com.google.android.gms.fitness.data.Field FIELD_MEAL_TYPE = formatIntOptionalField("meal_type");
- public static final com.google.android.gms.fitness.data.Field FIELD_FOOD_ITEM = formatStringOptionalField("food_item");
- public static final com.google.android.gms.fitness.data.Field FIELD_NUTRIENTS = formatMapField("nutrients");
- public static final com.google.android.gms.fitness.data.Field FIELD_EXERCISE = formatStringField("exercise");
- public static final com.google.android.gms.fitness.data.Field FIELD_REPETITIONS = formatIntOptionalField("repetitions");
- public static final com.google.android.gms.fitness.data.Field FIELD_RESISTANCE = formatFloatOptionalField("resistance");
- public static final com.google.android.gms.fitness.data.Field FIELD_RESISTANCE_TYPE = formatIntOptionalField("resistance_type");
- public static final com.google.android.gms.fitness.data.Field FIELD_NUM_SEGMENTS = formatIntField("num_segments");
- public static final com.google.android.gms.fitness.data.Field FIELD_AVERAGE = formatFloatField("average");
- public static final com.google.android.gms.fitness.data.Field FIELD_MAX = formatFloatField("max");
- public static final com.google.android.gms.fitness.data.Field FIELD_MIN = formatFloatField("min");
- public static final com.google.android.gms.fitness.data.Field FIELD_LOW_LATITUDE = formatFloatField("low_latitude");
- public static final com.google.android.gms.fitness.data.Field FIELD_LOW_LONGITUDE = formatFloatField("low_longitude");
- public static final com.google.android.gms.fitness.data.Field FIELD_HIGH_LATITUDE = formatFloatField("high_latitude");
- public static final com.google.android.gms.fitness.data.Field FIELD_HIGH_LONGITUDE = formatFloatField("high_longitude");
- public static final com.google.android.gms.fitness.data.Field FIELD_OCCURRENCES = formatIntField("occurrences");
- public static final com.google.android.gms.fitness.data.Field FIELD_SENSOR_TYPE = formatIntField("sensor_type");
- public static final com.google.android.gms.fitness.data.Field FIELD_TIMESTAMPS = formatLongField("timestamps");
- public static final com.google.android.gms.fitness.data.Field FIELD_SENSOR_VALUES = formatDoubleField("sensor_values");
- public static final com.google.android.gms.fitness.data.Field FIELD_INTENSITY = formatFloatField("intensity");
- public static final com.google.android.gms.fitness.data.Field FIELD_ACTIVITY_CONFIDENCE = formatMapField("activity_confidence");
- public static final com.google.android.gms.fitness.data.Field FIELD_PROBABILITY = formatFloatField("probability");
- public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_SLEEP_ATTRIBUTES = formatObjectField("google.android.fitness.SleepAttributes");
- public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_SLEEP_SCHEDULE = formatObjectField("google.android.fitness.SleepSchedule");
- @Deprecated
- public static final com.google.android.gms.fitness.data.Field FIELD_CIRCUMFERENCE = formatFloatField("circumference");
- public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_PACED_WALKING_ATTRIBUTES = formatObjectField("google.android.fitness.PacedWalkingAttributes");
- public static final com.google.android.gms.fitness.data.Field FIELD_ZONE_ID = formatStringField("zone_id");
- public static final com.google.android.gms.fitness.data.Field FIELD_MET = formatFloatField("met");
-
+ /**
+ * Format constant indicating the field holds integer values.
+ */
public static final int FORMAT_INT32 = 1;
+ /**
+ * Format constant indicating the field holds float values.
+ */
public static final int FORMAT_FLOAT = 2;
+ /**
+ * Format constant indicating the field holds string values. Strings should be kept small whenever possible. Data streams with large string
+ * values and high data frequency may be down sampled.
+ */
public static final int FORMAT_STRING = 3;
+ /**
+ * Format constant indicating the field holds a map of string keys to values. The valid key space and units for the corresponding value should
+ * be documented as part of the data type definition.
+ *
+ * Map values can be set using {@link DataPoint.Builder#setField(com.google.android.gms.fitness.data.Field, java.util.Map)}.
+ *
+ * Keys should be kept small whenever possible. Data streams with large keys and high data frequency may be down sampled.
+ */
public static final int FORMAT_MAP = 4;
+
public static final int FORMAT_LONG = 5;
public static final int FORMAT_DOUBLE = 6;
public static final int FORMAT_OBJECT = 7;
- @Field(1)
- public String name;
- @Field(2)
- public int format;
- @Field(3)
- public Boolean optional;
+ /**
+ * Meal type constant representing that the meal type is unknown.
+ */
+ public static final int MEAL_TYPE_UNKNOWN = 0;
+ /**
+ * Meal type constant representing a breakfast meal.
+ */
+ public static final int MEAL_TYPE_BREAKFAST = 1;
+ /**
+ * Meal type constant representing a lunch meal.
+ */
+ public static final int MEAL_TYPE_LUNCH = 2;
+ /**
+ * Meal type constant representing a dinner meal.
+ */
+ public static final int MEAL_TYPE_DINNER = 3;
+ /**
+ * Meal type constant representing a snack meal.
+ */
+ public static final int MEAL_TYPE_SNACK = 4;
+ /**
+ * Calcium amount in milligrams.
+ */
+ @NonNull
+ public static final String NUTRIENT_CALCIUM = "calcium";
+ /**
+ * Calories in kcal.
+ */
+ @NonNull
+ public static final String NUTRIENT_CALORIES = "calories";
+ /**
+ * Cholesterol in milligrams.
+ */
+ @NonNull
+ public static final String NUTRIENT_CHOLESTEROL = "cholesterol";
+ /**
+ * Dietary fiber in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_DIETARY_FIBER = "dietary_fiber";
+ /**
+ * Iron amount in milligrams.
+ */
+ @NonNull
+ public static final String NUTRIENT_IRON = "iron";
+ /**
+ * Monounsaturated fat in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_MONOUNSATURATED_FAT = "fat.monounsaturated";
+ /**
+ * Polyunsaturated fat in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_POLYUNSATURATED_FAT = "fat.polyunsaturated";
+ /**
+ * Potassium in milligrams.
+ */
+ @NonNull
+ public static final String NUTRIENT_POTASSIUM = "potassium";
+ /**
+ * Protein amount in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_PROTEIN = "protein";
+ /**
+ * Saturated fat in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_SATURATED_FAT = "fat.saturated";
+ /**
+ * Sodium in milligrams.
+ */
+ @NonNull
+ public static final String NUTRIENT_SODIUM = "sodium";
+ /**
+ * Sugar amount in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_SUGAR = "sugar";
+ /**
+ * Total carbohydrates in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_TOTAL_CARBS = "carbs.total";
+ /**
+ * Total fat in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_TOTAL_FAT = "fat.total";
+ /**
+ * Trans fat in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_TRANS_FAT = "fat.trans";
+ /**
+ * Unsaturated fat in grams.
+ */
+ @NonNull
+ public static final String NUTRIENT_UNSATURATED_FAT = "fat.unsaturated";
+ /**
+ * Vitamin A amount in International Units (IU). For converting from daily percentages, the FDA recommended 5000 IUs Daily Value can be
+ * used.
+ */
+ @NonNull
+ public static final String NUTRIENT_VITAMIN_A = "vitamin_a";
+ /**
+ * Vitamin C amount in milligrams.
+ */
+ @NonNull
+ public static final String NUTRIENT_VITAMIN_C = "vitamin_c";
+ /**
+ * The resistance type is unknown, unspecified, or not represented by any canonical values.
+ */
+ public static final int RESISTANCE_TYPE_UNKNOWN = 0;
+ /**
+ * The user is using a barbell for resistance. The specified resistance should include the weight of the bar, as well as weights added to both
+ * sides.
+ */
+ public static final int RESISTANCE_TYPE_BARBELL = 1;
+ /**
+ * The user is using a cable for resistance. When two cables are being used (one for each arm), the specified resistance should include the
+ * weight being pulled by one cable.
+ */
+ public static final int RESISTANCE_TYPE_CABLE = 2;
+ /**
+ * The user is using dumbells for resistance. The specified resistance should include the weight of a single dumbell.
+ */
+ public static final int RESISTANCE_TYPE_DUMBBELL = 3;
+ /**
+ * The user is using a kettlebell for resistance.
+ */
+ public static final int RESISTANCE_TYPE_KETTLEBELL = 4;
+ /**
+ * The user is performing the exercise in a machine. The specified resistance should match the weight specified by the machine.
+ */
+ public static final int RESISTANCE_TYPE_MACHINE = 5;
+ /**
+ * The user is using their own body weight for resistance.
+ */
+ public static final int RESISTANCE_TYPE_BODY = 6;
+ /**
+ * The accuracy of an accompanied value (such as location).
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_ACCURACY = createFloatField("accuracy");
+ /**
+ * An activity type of {@link FitnessActivities}, encoded as an integer for efficiency. The activity value should be stored using
+ * {@link DataPoint.Builder#setActivityField(Field, String)}.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_ACTIVITY = createIntField("activity");
+ /**
+ * An altitude of a location represented as a float, in meters above sea level. Some location samples don't have an altitude value so this field
+ * might not be set.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_ALTITUDE = createOptionalFloatField("altitude");
+ /**
+ * An average value.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_AVERAGE = createFloatField("average");
+ /**
+ * A heart rate in beats per minute.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_BPM = createFloatField("bpm");
+ /**
+ * Calories in kcal.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_CALORIES = createFloatField("calories");
+ /**
+ * Circumference of a body part, in centimeters.
+ *
+ * @deprecated There is no applicable replacement field.
+ */
+ @Deprecated
+ public static final com.google.android.gms.fitness.data.Field FIELD_CIRCUMFERENCE = createFloatField("circumference");
+ /**
+ * The confidence of an accompanied value, specified as a value between 0.0 and 100.0.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_CONFIDENCE = createFloatField("confidence");
+ /**
+ * A distance in meters.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_DISTANCE = createFloatField("distance");
+ /**
+ * A field containing duration. The units of the field are defined by the outer data type.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_DURATION = createIntField("duration");
+ /**
+ * A workout exercise, as represented by one of the constants in {@link WorkoutExercises}.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_EXERCISE = createStringField("exercise");
+ /**
+ * The corresponding food item for a nutrition entry.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_FOOD_ITEM = createOptionalStringField("food_item");
+ /**
+ * A height in meters.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_HEIGHT = createFloatField("height");
+ /**
+ * A high latitude of a location bounding box represented as a float, in degrees.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_HIGH_LATITUDE = createFloatField("high_latitude");
+ /**
+ * A high longitude of a location bounding box represented as a float, in degrees.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_HIGH_LONGITUDE = createFloatField("high_longitude");
+ /**
+ * Intensity of user activity, represented as a float.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_INTENSITY = createFloatField("intensity");
+ /**
+ * A latitude of a location represented as a float, in degrees.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_LATITUDE = createFloatField("latitude");
+ /**
+ * A longitude of a location represented as a float, in degrees.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_LONGITUDE = createFloatField("longitude");
+ /**
+ * A low latitude of a location bounding box represented as a float, in degrees.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_LOW_LATITUDE = createFloatField("low_latitude");
+ /**
+ * A low longitude of a location bounding box represented as a float, in degrees.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_LOW_LONGITUDE = createFloatField("low_longitude");
+ /**
+ * A maximum value.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_MAX = createFloatField("max");
+ /**
+ * A maximum int value.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_MAX_INT = createIntField("max");
+ /**
+ * Type of meal, represented as the appropriate int constant.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_MEAL_TYPE = createOptionalIntField("meal_type");
+ /**
+ * A minimum value.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_MIN = createFloatField("min");
+ /**
+ * A minimum int value.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_MIN_INT = createIntField("min");
+ /**
+ * A number of segments.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_NUM_SEGMENTS = createIntField("num_segments");
+ /**
+ * Nutrients ingested by the user, represented as a float map of nutrient key to quantity. The valid keys of the map are listed in this class using
+ * the {@code NUTRIENT_} prefix. The documentation for each key describes the unit of its value.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_NUTRIENTS = createMapField("nutrients");
+ /**
+ * How many occurrences of an event there were in a time range. For sample data types this should not be set to more than one.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_OCCURRENCES = createIntField("occurrences");
+ /**
+ * A percentage value, between 0 and 100.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_PERCENTAGE = createFloatField("percentage");
+ /**
+ * A count of repetitions for a single set of a workout exercise.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_REPETITIONS = createOptionalIntField("repetitions");
+ /**
+ * The resistance of the exercise (or weight), in kg.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_RESISTANCE = createOptionalFloatField("resistance");
+ /**
+ * The type of resistance used in this exercise, represented as the appropriate int constant.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_RESISTANCE_TYPE = createOptionalIntField("resistance_type");
+ /**
+ * A count of revolutions.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_REVOLUTIONS = createIntField("revolutions");
+ /**
+ * Revolutions per minute or rate per minute.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_RPM = createFloatField("rpm");
+ /**
+ * Sleep Segment type defined in {@link SleepStages}.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_SLEEP_SEGMENT_TYPE = createIntField("sleep_segment_type");
+ /**
+ * A speed in meter/sec.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_SPEED = createFloatField("speed");
+ /**
+ * A count of steps.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_STEPS = createIntField("steps");
+ /**
+ * Distance between steps in meters.
+ *
+ * @deprecated There is no applicable replacement field.
+ */
+ @Deprecated
+ public static final com.google.android.gms.fitness.data.Field FIELD_STEP_LENGTH = createFloatField("step_length");
+ /**
+ * Volume in liters.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_VOLUME = createFloatField("volume");
+ /**
+ * Power in watts.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_WATTS = createFloatField("watts");
+ /**
+ * A weight in kilograms.
+ */
+ public static final com.google.android.gms.fitness.data.Field FIELD_WEIGHT = createFloatField("weight");
- public Field() {
- }
+ public static final com.google.android.gms.fitness.data.Field FIELD_ACTIVITY_CONFIDENCE = createMapField("activity_confidence");
+ public static final com.google.android.gms.fitness.data.Field FIELD_ACTIVITY_DURATION_ASCENDING = createMapField("activity_duration.ascending");
+ public static final com.google.android.gms.fitness.data.Field FIELD_ACTIVITY_DURATION_DESCENDING = createMapField("activity_duration.descending");
+ public static final com.google.android.gms.fitness.data.Field FIELD_DURATION_OPTIONAL = createOptionalIntField("duration");
+ public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_DEVICE = createObjectField("google.android.fitness.Device");
+ public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_GOAL_V2 = createObjectField("google.android.fitness.GoalV2");
+ public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_SLEEP_ATTRIBUTES = createObjectField("google.android.fitness.SleepAttributes");
+ public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_SLEEP_SCHEDULE = createObjectField("google.android.fitness.SleepSchedule");
+ public static final com.google.android.gms.fitness.data.Field FIELD_FITNESS_PACED_WALKING_ATTRIBUTES = createObjectField("google.android.fitness.PacedWalkingAttributes");
+ public static final com.google.android.gms.fitness.data.Field FIELD_MET = createFloatField("met");
+ public static final com.google.android.gms.fitness.data.Field FIELD_PROBABILITY = createFloatField("probability");
+ public static final com.google.android.gms.fitness.data.Field FIELD_RESPIRATORY_RATE = createFloatField("respiratory_rate");
+ public static final com.google.android.gms.fitness.data.Field FIELD_SENSOR_TYPE = createIntField("sensor_type");
+ public static final com.google.android.gms.fitness.data.Field FIELD_SENSOR_VALUES = createDoubleField("sensor_values");
+ public static final com.google.android.gms.fitness.data.Field FIELD_TIMESTAMPS = createLongField("timestamps");
+ public static final com.google.android.gms.fitness.data.Field FIELD_ZONE_ID = createStringField("zone_id");
+
+ @Field(value = 1, getterName = "getName")
+ @NonNull
+ private final String name;
+ @Field(value = 2, getterName = "getFormat")
+ private final int format;
+ @Field(value = 3, getterName = "isOptional")
+ @Nullable
+ private final Boolean optional;
- public Field(String name, int format, Boolean optional) {
+ @Constructor
+ public Field(@Param(1) @NonNull String name, @Param(2) int format, @Param(3) @Nullable Boolean optional) {
this.name = name;
this.format = format;
this.optional = optional;
}
- public Field(String name, int format) {
+ public Field(@NonNull String name, int format) {
this(name, format, null);
}
- public static com.google.android.gms.fitness.data.Field formatIntField(String name) {
+ /**
+ * Returns the format of the field, as one of the format constant values.
+ */
+ public int getFormat() {
+ return format;
+ }
+
+ /**
+ * Returns the name of the field.
+ */
+ public String getName() {
+ return name;
+ }
+
+ public Boolean isOptional() {
+ return optional;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public final boolean equals(Object o) {
+ if (!(o instanceof com.google.android.gms.fitness.data.Field)) return false;
+
+ com.google.android.gms.fitness.data.Field field = (com.google.android.gms.fitness.data.Field) o;
+ return format == field.format && name.equals(field.name);
+ }
+
+ public static com.google.android.gms.fitness.data.Field createIntField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_INT32);
}
- public static com.google.android.gms.fitness.data.Field formatFloatField(String name) {
+ public static com.google.android.gms.fitness.data.Field createFloatField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_FLOAT);
}
- public static com.google.android.gms.fitness.data.Field formatStringField(String name) {
+ public static com.google.android.gms.fitness.data.Field createStringField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_STRING);
}
- public static com.google.android.gms.fitness.data.Field formatMapField(String name) {
+ public static com.google.android.gms.fitness.data.Field createMapField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_MAP);
}
- public static com.google.android.gms.fitness.data.Field formatLongField(String name) {
+ public static com.google.android.gms.fitness.data.Field createLongField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_LONG);
}
- public static com.google.android.gms.fitness.data.Field formatDoubleField(String name) {
+ public static com.google.android.gms.fitness.data.Field createDoubleField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_DOUBLE);
}
- public static com.google.android.gms.fitness.data.Field formatObjectField(String name) {
+ public static com.google.android.gms.fitness.data.Field createObjectField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_OBJECT);
}
- public static com.google.android.gms.fitness.data.Field formatIntOptionalField(String name) {
+ public static com.google.android.gms.fitness.data.Field createOptionalIntField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_INT32, true);
}
- public static com.google.android.gms.fitness.data.Field formatFloatOptionalField(String name) {
+ public static com.google.android.gms.fitness.data.Field createOptionalFloatField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_FLOAT, true);
}
- public static com.google.android.gms.fitness.data.Field formatStringOptionalField(String name) {
+ public static com.google.android.gms.fitness.data.Field createOptionalStringField(String name) {
return new com.google.android.gms.fitness.data.Field(name, FORMAT_STRING, true);
}
diff --git a/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/MapValue.java b/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/MapValue.java
new file mode 100644
index 0000000000..f03711f100
--- /dev/null
+++ b/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/MapValue.java
@@ -0,0 +1,60 @@
+/*
+ * SPDX-FileCopyrightText: 2024 microG Project Team
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.google.android.gms.fitness.data;
+
+import android.os.Parcel;
+import androidx.annotation.NonNull;
+import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
+import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
+import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
+import org.microg.gms.common.Hide;
+
+import static com.google.android.gms.fitness.data.Field.FORMAT_FLOAT;
+
+@Hide
+@SafeParcelable.Class
+public class MapValue extends AbstractSafeParcelable {
+ @Field(value = 1, getterName = "getFormat")
+ private final int format;
+ @Field(value = 2, getterName = "getValue")
+ private final float value;
+
+ @Constructor
+ public MapValue(@Param(1) int format, @Param(2) float value) {
+ this.format = format;
+ this.value = value;
+ }
+
+ @NonNull
+ public static MapValue ofFloat(float value) {
+ return new MapValue(FORMAT_FLOAT, value);
+ }
+
+ public int getFormat() {
+ return format;
+ }
+
+ float getValue() {
+ return value;
+ }
+
+ public float asFloat() {
+ if (format != FORMAT_FLOAT) throw new IllegalStateException("MapValue is not a float");
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) value;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ CREATOR.writeToParcel(this, dest, flags);
+ }
+
+ public static final SafeParcelableCreatorAndWriter
+ * The session's activity type is returned by {@link #getActivity()}. The MIME type can be computed from the activity using {@link #getMimeType(String)}
+ */
+ @NonNull
+ public static final String MIME_TYPE_PREFIX = "vnd.google.fitness.session/";
+
+ @Field(value = 1, getterName = "getStartTimeMillis")
+ private final long startTimeMillis;
+ @Field(value = 2, getterName = "getEndTimeMillis")
+ private final long endTimeMillis;
+ @Field(value = 3, getterName = "getName")
+ @Nullable
+ private final String name;
+ @Field(value = 4, getterName = "getIdentifier")
+ @NonNull
+ private final String identifier;
+ @Field(value = 5, getterName = "getDescription")
+ @NonNull
+ private final String description;
+ @Field(value = 7, getterName = "getActivityType")
+ private final int activityType;
+ @Field(value = 8, getterName = "getApplication")
+ private final Application application;
+ @Field(value = 9, getterName = "getActiveTimeMillis")
+ @Nullable
+ private final Long activeTimeMillis;
+
+ @Constructor
+ Session(@Param(1) long startTimeMillis, @Param(2) long endTimeMillis, @Param(3) @Nullable String name, @Param(4) @NonNull String identifier, @Param(5) @NonNull String description, @Param(7) int activityType, @Param(8) Application application, @Param(9) @Nullable Long activeTimeMillis) {
+ this.startTimeMillis = startTimeMillis;
+ this.endTimeMillis = endTimeMillis;
+ this.name = name;
+ this.identifier = identifier;
+ this.description = description;
+ this.activityType = activityType;
+ this.application = application;
+ this.activeTimeMillis = activeTimeMillis;
+ }
+
+ /**
+ * Returns the active time period of the session.
+ *
+ * Make sure to use {@link #hasActiveTime()} before using this method.
+ *
+ * @throws IllegalStateException {@link #hasActiveTime()} returns false.
+ */
+ public long getActiveTime(@NonNull TimeUnit timeUnit) {
+ if (activeTimeMillis == null) throw new IllegalStateException("Active time is not set");
+ return timeUnit.convert(activeTimeMillis, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Returns the activity associated with this session, if set. Else returns {@link FitnessActivities#UNKNOWN}.
+ */
+ @NonNull
+ public String getActivity() {
+ return null; // TODO
+ }
+
+ /**
+ * Returns the package name for the application responsible for adding the session. or {@code null} if unset/unknown. The {@link PackageManager} can be
+ * used to query relevant data on the application, such as the name, icon, or logo.
+ */
+ @Nullable
+ public String getAppPackageName() {
+ if (application == null) return null;
+ return application.getPackageName();
+ }
+
+ /**
+ * Returns the description for this session.
+ */
+ @NonNull
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Returns the end time for the session, in the given unit since epoch. If the session is ongoing (it hasn't ended yet), this will return 0.
+ */
+ public long getEndTime(@NonNull TimeUnit timeUnit) {
+ return timeUnit.convert(endTimeMillis, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Returns the identifier for this session.
+ */
+ @NonNull
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ /**
+ * Returns the name for this session, if set.
+ */
+ @Nullable
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the start time for the session, in the given time unit since epoch. A valid start time is always set.
+ */
+ public long getStartTime(@NonNull TimeUnit timeUnit) {
+ return timeUnit.convert(startTimeMillis, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Returns whether the session active time is set.
+ */
+ public boolean hasActiveTime() {
+ return activeTimeMillis != null;
+ }
+
+ /**
+ * Returns whether the session is ongoing. If the session has ended, this will return false.
+ */
+ public boolean isOngoing() {
+ return endTimeMillis == 0;
+ }
+
+ Application getApplication() {
+ return application;
+ }
+
+ int getActivityType() {
+ return activityType;
+ }
+
+ long getStartTimeMillis() {
+ return startTimeMillis;
+ }
+
+ long getEndTimeMillis() {
+ return endTimeMillis;
+ }
+
+ @Nullable
+ Long getActiveTimeMillis() {
+ return activeTimeMillis;
+ }
+
+ /**
+ * Extracts the session extra from the given intent, such as a callback intent received after registering to session start/end notifications, or an intent to view a session.
+ *
+ * @param intent The extracted Session, or {@code null} if the given intent does not contain a Session.
+ */
+ @Nullable
+ public static Session extract(@NonNull Intent intent) {
+ return SafeParcelableSerializer.deserializeFromBytes(intent.getByteArrayExtra(EXTRA_SESSION), CREATOR);
+ }
+
+ /**
+ * Returns the MIME type which describes a Session for a particular activity. The MIME type is used in intents such as the session view
+ * intent.
+ *
+ * @param activity One of the activities in {@link FitnessActivities}.
+ */
+ @NonNull
+ public static String getMimeType(@NonNull String activity) {
+ return MIME_TYPE_PREFIX + activity;
+ }
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
diff --git a/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/SessionDataSet.java b/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/SessionDataSet.java
new file mode 100644
index 0000000000..7037956f24
--- /dev/null
+++ b/play-services-fitness/src/main/java/com/google/android/gms/fitness/data/SessionDataSet.java
@@ -0,0 +1,37 @@
+/*
+ * SPDX-FileCopyrightText: 2024 microG Project Team
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.google.android.gms.fitness.data;
+
+import android.os.Parcel;
+
+import androidx.annotation.NonNull;
+
+import com.google.android.gms.common.internal.safeparcel.AbstractSafeParcelable;
+import com.google.android.gms.common.internal.safeparcel.SafeParcelable;
+import com.google.android.gms.common.internal.safeparcel.SafeParcelableCreatorAndWriter;
+import org.microg.gms.common.Hide;
+
+@SafeParcelable.Class
+@Hide
+public class SessionDataSet extends AbstractSafeParcelable {
+ public static final SafeParcelableCreatorAndWriter
+ * A field value has a particular format, and should be set and read using the format-specific methods. For instance, a float value should be set
+ * via {@link #setFloat(float)} and read via {@link #asFloat()}. Formats are defined as constants in {@link com.google.android.gms.fitness.data.Field}.
+ */
+@SafeParcelable.Class
+public final class Value extends AbstractSafeParcelable {
+ @Field(value = 1, getterName = "getFormat")
+ public int format;
+ @Field(value = 2, getterName = "isSet")
+ public boolean set;
+ @Field(value = 3, getterName = "getValue")
+ public float value;
+ @Field(value = 4, getterName = "getStringValue")
+ public String stringValue;
+ @Field(value = 5, getterName = "getMapValue")
+ @Nullable
+ public Bundle mapValue;
+ @Field(value = 6, getterName = "getIntArrayValue")
+ public int[] intArrayValue;
+ @Field(value = 7, getterName = "getFloatArrayValue")
+ public float[] floatArrayValue;
+ @Field(value = 8, getterName = "getBlob")
+ public byte[] blob;
+
+ @Constructor
+ public Value(@Param(1) int format, @Param(2) boolean set, @Param(3) float value, @Param(4) String stringValue, @Param(5) @Nullable Bundle mapValue, @Param(6) int[] intArrayValue, @Param(7) float[] floatArrayValue, @Param(8) byte[] blob) {
+ this.format = format;
+ this.set = set;
+ this.value = value;
+ this.stringValue = stringValue;
+ this.mapValue = mapValue;
+ this.intArrayValue = intArrayValue;
+ this.floatArrayValue = floatArrayValue;
+ this.blob = blob;
+ }
+
+ Value(int format) {
+ this(format, false, 0f, null, null, null, null, null);
+ }
+
+ /**
+ * Returns the value of this object as an activity. The integer representation of the activity is converted to a String prior to returning.
+ *
+ * @return One of the constants from {@link FitnessActivities}; {@link FitnessActivities#UNKNOWN} if the object does not hold a valid activity
+ * representation
+ * @throws IllegalStateException If this {@link Value} does not correspond to a {@link com.google.android.gms.fitness.data.Field#FORMAT_INT32}
+ */
+ public String asActivity() {
+ return null; // TODO
+ }
+
+ /**
+ * Returns the value of this object as a float.
+ *
+ * @throws IllegalStateException If this {@link Value} does not correspond to a {@link com.google.android.gms.fitness.data.Field#FORMAT_FLOAT}
+ */
+ public float asFloat() {
+ if (format != FORMAT_FLOAT) throw new IllegalStateException("Value is not a float.");
+ return value;
+ }
+
+ /**
+ * Returns the value of this object as a int.
+ *
+ * @throws IllegalStateException If this {@link Value} does not correspond to a {@link com.google.android.gms.fitness.data.Field#FORMAT_INT32}
+ */
+ public int asInt() {
+ if (format != FORMAT_INT32) throw new IllegalStateException("Value is not a int.");
+ return Float.floatToRawIntBits(this.value);
+ }
+
+ /**
+ * Returns the value of this object as a string.
+ *
+ * @throws IllegalStateException If this {@link Value} does not correspond to a {@link com.google.android.gms.fitness.data.Field#FORMAT_STRING}
+ */
+ @NonNull
+ public String asString() {
+ if (format != FORMAT_STRING) throw new IllegalStateException("Value is not a string.");
+ if (stringValue == null) return "";
+ return stringValue;
+ }
+
+ /**
+ * Clears any value currently associated with the given {@code key} in the map. This method can be used only on map values.
+ *
+ * @param key The key you're modifying.
+ * @deprecated Use {@link DataPoint.Builder} to construct new {@link DataPoint} instances.
+ */
+ @Deprecated
+ public void clearKey(String key) {
+ if (format != FORMAT_MAP) throw new IllegalStateException("Value is not a map.");
+ if (mapValue != null) {
+ mapValue.remove(key);
+ }
+ }
+
+ /**
+ * Returns the format of this value, which matches the appropriate field in the data type definition.
+ *
+ * @return One of the format constants from {@link com.google.android.gms.fitness.data.Field}.
+ */
+ public int getFormat() {
+ return format;
+ }
+
+ /**
+ * Returns the value of the given key in the map as a {@link Float}.
+ *
+ * @return {@code null} if the key doesn't have a set value in the map.
+ * @throws IllegalStateException If this {@link Value} does not correspond to a {@link com.google.android.gms.fitness.data.Field#FORMAT_MAP}
+ */
+ @Nullable
+ public Float getKeyValue(@NonNull String key) {
+ if (format != FORMAT_MAP) throw new IllegalStateException("Value is not a map.");
+ if (mapValue == null || !mapValue.containsKey(key)) {
+ return null;
+ }
+ mapValue.setClassLoader(MapValue.class.getClassLoader());
+ if (VERSION.SDK_INT >= 33) {
+ return mapValue.getParcelable(key, MapValue.class).asFloat();
+ } else {
+ //noinspection deprecation
+ return ((MapValue) mapValue.getParcelable(key)).asFloat();
+ }
+ }
+
+ /**
+ * Returns {@code true} if this object's value has been set by calling one of the setters.
+ */
+ public boolean isSet() {
+ return set;
+ }
+
+ float getValue() {
+ return value;
+ }
+
+ String getStringValue() {
+ return stringValue;
+ }
+
+ @Nullable
+ Bundle getMapValue() {
+ return mapValue;
+ }
+
+ int[] getIntArrayValue() {
+ return intArrayValue;
+ }
+
+ float[] getFloatArrayValue() {
+ return floatArrayValue;
+ }
+
+ byte[] getBlob() {
+ return blob;
+ }
+
+ /**
+ * Updates this value object to represent an activity value. Activities are internally represented as integers for storage.
+ *
+ * @param activity One of the activities from {@link FitnessActivities}
+ * @deprecated Use {@link DataPoint.Builder} to construct new {@link DataPoint} instances.
+ */
+ public void setActivity(String activity) {
+ setInt(0); // TODO
+ }
+
+ /**
+ * Updates this value object to represent a float value. Any previous values associated with this object are erased.
+ *
+ * @param value The new value that this objects holds.
+ * @deprecated Use {@link DataPoint.Builder} to construct new {@link DataPoint} instances.
+ */
+ public void setFloat(float value) {
+ if (format != FORMAT_FLOAT) throw new IllegalStateException("Value is not a float.");
+ this.set = true;
+ this.value = value;
+ }
+
+ /**
+ * Updates this value object to represent an int value. Any previous values are erased.
+ *
+ * @param value The new value that this object holds.
+ * @deprecated Use {@link DataPoint.Builder} to construct new {@link DataPoint} instances.
+ */
+ public void setInt(int value) {
+ if (format != FORMAT_INT32) throw new IllegalStateException("Value is not a int.");
+ this.set = true;
+ this.value = Float.intBitsToFloat(value);
+ }
+
+ /**
+ * Updates the value for a given key in the map to the given float value. Any previous values associated with the key are erased. This method
+ * can be used only on map values.
+ *
+ * Key values should be kept small whenever possible. This is specially important for high frequency streams, since large keys may result in
+ * down sampling.
+ *
+ * @param key The key you're modifying.
+ * @param value The new value for the given key.
+ * @deprecated Use {@link DataPoint.Builder} to construct new {@link DataPoint} instances.
+ */
+ public void setKeyValue(String key, float value) {
+ if (format != FORMAT_MAP) throw new IllegalStateException("Value is not a map.");
+ this.set = true;
+ if (mapValue == null) mapValue = new Bundle();
+ mapValue.putParcelable(key, MapValue.ofFloat(value));
+ }
+
+ void setMap(@NonNull Map
+ * String values should be kept small whenever possible. This is specially important for high frequency streams, since large values may result
+ * in down sampling.
+ *
+ * @param value The new value that this objects holds.
+ * @deprecated Use {@link DataPoint.Builder} to construct new {@link DataPoint} instances.
+ */
+ public void setString(String value) {
+ if (format != FORMAT_STRING) throw new IllegalStateException("Value is not a string.");
+ this.set = true;
+ this.stringValue = value;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ CREATOR.writeToParcel(this, dest, flags);
+ }
+
+ public static final SafeParcelableCreatorAndWriter
+ * The method {@link #getStatus()} can be used to confirm if the request was successful. On success, the returned data type can be accessed
+ * via {@link #getDataType()}.
+ *
+ * In case the calling app is missing the required permissions, the returned status has status code set to
+ * {@link FitnessStatusCodes#NEEDS_OAUTH_PERMISSIONS}. In this case the caller should use {@link Status#startResolutionForResult(Activity, int)}
+ * to start an intent to get the necessary consent from the user before retrying the request.
+ *
+ * In case the app attempts to read a custom data type created by other app, the returned status has status code set to
+ * {@link FitnessStatusCodes#INCONSISTENT_DATA_TYPE}.
+ *
+ * @deprecated No replacement.
+ */
+@Deprecated
+@SafeParcelable.Class
+public class DataTypeResult extends AbstractSafeParcelable {
+
+ @Field(value = 1, getterName = "getStatus")
+ private final Status status;
+ @Field(value = 3, getterName = "getDataType")
+ @Nullable
+ private final DataType dataType;
+
+ @Constructor
+ @Hide
+ public DataTypeResult(@Param(1) Status status, @Param(3) @Nullable DataType dataType) {
+ this.status = status;
+ this.dataType = dataType;
+ }
+
+ /**
+ * Returns the new custom data type inserted, or {@code null} if the request failed.
+ */
+ @Nullable
+ public DataType getDataType() {
+ return dataType;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ CREATOR.writeToParcel(this, dest, flags);
+ }
+
+ public static final SafeParcelableCreatorAndWriter
+ * The method {@link #getStatus()} can be used to confirm if the request was successful.
+ *
+ * In case the calling app is missing the required permissions, the returned status has status code set to
+ * {@link FitnessStatusCodes#NEEDS_OAUTH_PERMISSIONS}. In this case the caller should use {@link Status#startResolutionForResult(Activity, int)}
+ * to start an intent to get the necessary consent from the user before retrying the request.
+ *
+ * The method {@link #getSessions()} returns all sessions that are returned for the request. The method {@link #getDataSet(Session, DataType)} returns
+ * {@link DataSet} for a particular Session and {@link DataType} from the result.
+ *
+ * In case the app tried to read data for a custom data type created by another app, the returned status has status code set to
+ * {@link FitnessStatusCodes#INCONSISTENT_DATA_TYPE}.
+ */
+@SafeParcelable.Class
+public class SessionReadResult extends AbstractSafeParcelable {
+ @Field(value = 1, getterName = "getSessions")
+ @NonNull
+ private final List
+ * The method {@link #getStatus()} can be used to confirm if the request was successful.
+ *
+ * In case the calling app is missing the required permissions, the returned status has status code set to
+ * {@link FitnessStatusCodes#NEEDS_OAUTH_PERMISSIONS}. In this case the caller should use {@link Status#startResolutionForResult(Activity, int)}
+ * to start an intent to get the necessary consent from the user before retrying the request.
+ */
+@SafeParcelable.Class
+public class SessionStopResult extends AbstractSafeParcelable {
+ @Field(value = 2, getterName = "getStatus")
+ @NonNull
+ private final Status status;
+ @Field(value = 3, getterName = "getSessions")
+ @NonNull
+ private final List
+ *
+ */
+ @NonNull
+ public String getStreamIdentifier() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(type == TYPE_RAW ? "raw" : "derived");
+ sb.append(":").append(dataType.getName());
+ if (application != null) sb.append(":").append(application.getPackageName());
+ if (device != null) sb.append(":").append(device.getDeviceId());
+ if (streamName != null) sb.append(":").append(streamName);
+ return sb.toString();
+ }
+
+ /**
+ * Returns the specific stream name for the stream coming from this data source, or an empty string if unset.
+ */
+ @NonNull
+ public String getStreamName() {
+ return streamName;
+ }
+
+ /**
+ * Returns the constant describing the type of this data source.
+ *
+ * @return One of the constant values ({@link #TYPE_DERIVED} or {@link #TYPE_RAW}), zero if unset. Values outside of this range should be treated as
+ * unset/unknown.
+ */
+ public int getType() {
+ return type;
+ }
+
+ @Override
+ public int hashCode() {
+ return getStreamIdentifier().hashCode();
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return ToStringHelper.name("DataSource").value(getStreamIdentifier()).end();
+ }
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
CREATOR.writeToParcel(this, dest, flags);
}
+ /**
+ * Extracts the data source extra from the given intent, such as an intent to view user's data.
+ *
+ * @return The data source, or {@code null} if not found.
+ */
+ @Nullable
+ public static DataSource extract(@NonNull Intent intent) {
+ return SafeParcelableSerializer.deserializeFromBytes(intent.getByteArrayExtra(EXTRA_DATA_SOURCE), CREATOR);
+ }
+
+ /**
+ * A builder that can be used to construct new data source objects. In general, a built data source should be saved in memory to avoid the cost
+ * of re-constructing it for every request.
+ */
+ public static class Builder {
+ private DataType dataType;
+ private Device device;
+ private Application application;
+ private int type = -1;
+ private String streamName = "";
+
+ /**
+ * Finishes building the data source and returns a DataSource object.
+ *
+ * @throws IllegalStateException If the builder didn't have enough data to build a valid data source.
+ */
+ @NonNull
+ public DataSource build() {
+ if (dataType == null) throw new IllegalStateException("dataType must be set");
+ if (type < 0) throw new IllegalStateException("type must be set");
+ return new DataSource(dataType, type, device, application, streamName);
+ }
+
+ /**
+ * Sets the package name for the application that is recording or computing the data. Used for data sources that aren't built into the platform
+ * (local sensors and BLE sensors are built-in). It can be used to identify the data source, to disambiguate between data from different
+ * applications, and also to link back to the original application for a detailed view.
+ */
+ @NonNull
+ public Builder setAppPackageName(@NonNull String packageName) {
+ Application application = Application.GMS_APP;
+ this.application = Constants.GMS_PACKAGE_NAME.equals(packageName) ? Application.GMS_APP : new Application(packageName);
+ return this;
+ }
+
+ /**
+ * Sets the package name for the application that is recording or computing the data based on the app's context. This method should be
+ * preferred when an application is creating a data source that represents its own data. When creating a data source to query data from other
+ * apps, {@link #setAppPackageName(String)} should be used.
+ */
+ @NonNull
+ public Builder setAppPackageName(@NonNull Context appContext) {
+ setAppPackageName(appContext.getPackageName());
+ return this;
+ }
+
+ /**
+ * Sets the data type for the data source. Every data source is required to have a data type.
+ *
+ * @param dataType One of the data types defined in {@link DataType}, or a custom data type.
+ */
+ @NonNull
+ public Builder setDataType(@NonNull DataType dataType) {
+ this.dataType = dataType;
+ return this;
+ }
+
+ /**
+ * Sets the integrated device where data is being recorded (for instance, a phone that has sensors, or a wearable). Can be useful to identify the
+ * data source, and to disambiguate between data from different devices. If the data is coming from the local device, use
+ * {@link Device#getLocalDevice(Context)}.
+ *