Chapter 9
Google Fit API

9.1 Google Fit API

The Google Fit API (also referred to simply as the Fit API) resides in the namespace com.google.android.gms.fitness and is available as part of Google Play Services. Any Google Fit App has a dependency on the Google Play Services App being installed on the device that it is running on.

9.2 Google fit main package (com.google.android.gms.fitness)

The Google Fit API documentation is available at https://developers.google.com/fit/android/reference and is a useful reference when reading this chapter.

In all, the main package fitness and its sub-packages contain about eight high-level interfaces and 30 high-level classes. The main package fitness contains four sub-packages: data, service, request, and result. The fitness package itself contains the interfaces SensorsApi, BleApi (Bluetooth Low Energy API), SensorsApi, RecordingApi, HistoryApi, and SessionsApi, as well as the classes Fitness, FitnessActivities, and FitnessStatusCodes.

Figure 9-1 shows the classes and interfaces within the main fitness package, as well as the sub-packages data, request, result, and service.

c9-fig-0001

Figure 9-1 Google Fit’s fitness package, high-level overview.

9.2.1 Fitness class

The Fitness class is the entry point into the Google Fit API. In order for a Fit App to connect to the Fit API, a Google user account is required on the device. The Fit App needs to specify the scope depending on the data and mode of access desired by the App. The GoogleApiClient uses the user account and scope information to get the OAuth tokens on behalf of the App, which ensures that only Apps with the necessary permissions can access specific data in the right mode of read or write—after explicit user consent.

An instance of Fitness is obtained via using the GoogleApiClient’s Builder, adding the Fitness API, specifying the Google account, and adding the scope. The following snippet in the user interface Activity’s onCreate() method shows how the Activity can connect the GoogleApiClient with the Fitness API added and enabled:

You will notice that the Google Fit App needs to add the “Fitness” API in order to access Google Fit. The main package is named fitness, and the Fitness class is the entry point into the Google Fit API. Therefore, the Fit API is sometimes also referred to as the Fitness API.

The user interface Activity that needs to access the Fit API will typically need to implement several listeners such as the GoogleApiClient’s ConnectionCallbacks and OnConnectionFailedListener as well as OnDataPointListener from the Fit API.

Figure 9-2 shows a partial listing of the attributes and methods available in the Fitness class.

c9-fig-0002

Figure 9-2 Fitness class, partial listing.

At runtime, the Fit API will become available only after the GoogleApiClient instance has connected successfully. After connecting successfully, the various specific APIs within the Fitness API such as BleApi, SensorsApi, SessionsApi, RecordingApi, HistoryApi, and ConfigApi can all be accessed via the Fitness class.

The Fitness class defines several ACTION families of Intents as static attributes that support collaboration between different Fit Apps. The ACTION_VIEW defines an Intent to view fitness data, while the ACTION_TRACK pertains to tracking a fitness activity; the ACTION_VIEW_GOAL defines an Intent to view a fitness goal. Associated with these actions/Intents are several extras, that is, Bundles of additional information that can be accessed via the call to Intent.getExtras(); a Bundle is a mapping between a key and a value. The Fitness class defines extras for the start time (EXTRA_START_TIME) and end time (EXTRA_END_TIME). Based on the particular action/Intent, there are particular relevant extras. The action ACTION_VIEW_GOAL, for instance, has the attribute of mimeType, the EXTRA_START_TIME and EXTRA_END_TIME and DataSource.EXTRA_DATA_SOURCE. Because these Intents are intended for collaboration between Apps, it is important to standardize on the names of extras using static final attributes. When you use extras with Intents within the same app too, it is a good programming practice to define the value of the key as a static final constant so that different components within your App can access the extra using the static final constant, rather than hard-coded values, which can be error prone.

The Fitness class also defines several SCOPEs for physical activity, body, and location, in read and write mode.

9.2.2 FitnessActivities class

The FitnessActivities class provides an elaborate set of public static final String constants that denote real-world physical activities such as BASEBALL, BIKING, RUNNING, WALKING, TENNIS, SWIMMING, SQUASH, MARTIAL_ARTS, DANCING, GARDENING, SLEEP, MEDITATION, and many more.

Figure 9-3 shows a few of the constants representing physical activities and sports. These constants are used in Sessions and DataTypes, which we will be covering in the next sections.

c9-fig-0003

Figure 9-3 FitnessActivities class, with a few constants listed.

9.2.3 FitnessStatusCodes class

The FitnessStatusCodes class defines about 18 constants that represent the result of requests made to the Google Fit API. The FitnessStatusCodes help in pinpointing the exception, error, or conflict when making a request to the Google Fit API. The request sub-package, which is covered in the next few sections contains various types of requests pertaining to Bluetooth LE (Ble), sensors, sessions, and so on. The result sub-package contains various types of corresponding results, which encapsulate the result data as well as the status. The App making the request needs to get the status in order to confirm that the request was successful or address the issue before making the attempt again.

Figure 9-4 shows a few of the constants available in the FitnessStatusCodes class.

c9-fig-0004

Figure 9-4 FitnessStatusCodes class, with a few constants listed.

9.2.4 BleApi interface

The BleApi is accessible via the static attribute available in the Fitness class. Prior to accessing BleApi, the GoogleApiClient must have connected successfully.

The BleApi provides functionality for scanning, claiming, and using Bluetooth Low Energy (Ble) Fitness devices. Many Bluetooth LE devices accept connections readily without the need for pairing. The concept of claiming a fitness device ensures that Google Fit apps connect only with fitness devices that the user owns and per the user’s intentions. The user needs to explicitly claim a device before it can be used by Google Fit in the sequential flow of scan/detect, claim, and use. Once a device is claimed, its data sources become available via the SensorsApi and the RecordingApi. Also, the App should use Google Fit to connect to the device rather than connect directly with the device (by using the base Android API’s android.bluetooth.* sub-packages and classes).

Figure 9-5 shows the BleApi interface with its methods related to scanning, claiming, and listing Bluetooth LE devices.

c9-fig-0005

Figure 9-5 BleApi.

The scan process is closely associated with StartBleScanRequest and the BleScanCallback both of which reside in the request package and have been covered in more detail in the next sections.

The following code snippet shows the creation of a scan request by using the StartBleScanRequest and the BleScanCallback classes. There must be at least one data type associated with the StartBleScanRequest:

The scan is asynchronous, and the BleScanCallback supports finding devices via the scan. Devices that are found can be claimed; however, any active Bluetooth scan operations should be stopped prior to claiming a device. The PendingResult has callbacks that can help the App determine the success or failure of the call.

The BleApi requires that Bluetooth is enabled in order for its methods to work. The FitnessStatusCode.DISABLED_BLUETOOTH represents the condition that Bluetooth is not enabled. Apps can address this by using the startResolutionForResult() method on the Status(com.google.gms.common.api). This starts the appropriate Intent that requires user interaction to resolve the condition. The PendingResult, which is used in all the BleApi method calls, is used in calls to the Google Play Services API.

9.2.5 SensorsApi

The SensorsApi provides access to live, real-time streams of sensor data from hardware sensors on the local device and companion devices. The SensorsApi is available as a static attribute on the Fitness class.

Figure 9-6 shows the methods available in the SensorsApi interface. The SensorsApi provides methods to add and remove listeners for sensor data. The add method whose parameters include a PendingIntent parameter is useful for slower sampling of sensor data. This method adds a PendingIntent listener to a sensor data source. Once the call to add succeeds, the PendingIntent’s callback will provide access to new sensor data, every time new data arrives. The application can extract the DataPoint (which encapsulates a sensor value and a timestamp) from the intent. DataPoint resides in the data package, which we will be covering shortly. There is another flavor of the add method whose parameters include an OnDataPointListener. This method is more appropriate for faster sampling rates using a live listener in the foreground. After the add succeeds, new DataPoints in the data stream are delivered to the specified listener.

c9-fig-0006

Figure 9-6 SensorsApi.

The following snippet shows an example of adding a sensor request:

The listeners need to be removed when the UI Activity is paused, stopped, or destroyed; and added again when the UI Activity resumes or restarts. The remove methods are used for removing the listener from the sensor data source. The findDataSources() method is used to find all available data sources for the specified data types. It is not necessary to call this method if your application is interested in getting the best available data of the specified data type, irrespective of the source, which may often be the case.

9.2.6 RecordingApi

The RecordingApi supports the collection, that is, recording of sensor data into the Google Fit Store in the background, in a low power consuming, always-on mode. The RecordingApi provides methods to subscribe to a given data type. Subscriptions persist device restarts and work in the background, irrespective of whether the subscribing App is running or not. Subscribing to a data type requires the user’s permission and consent, and the user can subsequently revoke such permission via the Google Play Services’ settings.

Figure 9-7 shows the methods in the RecordingApi, which include subscribe, unsubscribe, and listSubscriptions.

c9-fig-0007

Figure 9-7 RecordingApi.

The following code snippet shows the use of the SensorsApi to subscribe to a data type:

The RecordingApi, like the SensorsApi, becomes available only after a device has been successfully claimed via the BleApi. Unlike the SensorsApi, the RecordingApi does not deliver any live sensor data to the application. An App can have both a SensorsApi-based listener running and a RecordingApi-based subscription at the same time.

9.2.7 SessionsApi

The SessionsApi is useful for creating and managing sessions of user’s physical activity. A session represents a time interval during which a user engages in physical activity. A Session has a user-readable name such as “Morning Run,” a start time and associated data that is stored in the Fit Store. All the data within the time range is implicitly associated with the session. Session data is stored in a shareable manner and can be queried.

Figure 9-8 shows the methods in the SessionsApi interface. Once a session is started using the startSession method, session data can be stored in the Google Fit Store using the insertSession method using a SessionInsertRequest; also, any data that is inserted using the HistoryApi during the duration of the session will be associated with the session. Thus, insertSession and the HistoryApi methods represent two ways by which session data can be stored into the Google Fit Store.

c9-fig-0008

Figure 9-8 SessionsApi.

Once session data has been stored in the Google Fit Store, it can be retrieved by using the readSession method. The stopSession will terminate the session. The session also terminates upon the end of its duration when its end time has been reached. The registerForSessions method allows the application to be notified of session’s start and end events, via the PendingResult. The inner class SessionsApi.ViewIntentBuilder is useful for displaying detailed session data stored in the Google Fit Store.

The setting of the start time for the session is mandatory, while the end time is optional. The stopSession method available in the SessionsApi allows an application to stop a session. The following code snippet shows the use of the SessionsApi to start a new session of 20 minute duration:

After your App has created a session, you can insert the session and its associated data into the Google Fit Store. Your App can also read session data subsequently. There are Session Start and End intents that your App can register a broadcast listener for, in order to handle session starts and ends.

9.2.8 HistoryApi

The HistoryApi supports inserting, reading, and deleting data in the Google Fit Store. The HistoryApi also supports insertion of data that was collected outside of Google Fit, which can be useful if some readings were entered manually by the user or imported from a device that is not supported by Google Fit. The HistoryApi enables your App to perform bulk operations on the fitness store: inserting, deleting, and reading fitness data.

Figure 9-9 shows the methods available on the HistoryApi interface. The insertData method is useful for inserting data that was collected outside of Google Fit, including data entered manually by the user and/or bulk data. The readData method is useful for reading historical data.

c9-fig-0009

Figure 9-9 HistoryApi.

9.2.9 ConfigApi

The ConfigApi is useful for accessing settings in Google Fit as well as creating and accessing custom data types.

Figure 9-10 shows the methods available in the ConfigApi. The readDataType method is useful for retrieval of shareable data types added by other App or a custom data type added by your App. The createCustomDataType supports making a request to create a new data type and adding it to the Google Fit platform. The disableFit method supports disabling the App from Google Fit. Apps should provide users with the Disconnect from Google Fit option in the App’s settings. Disconnecting from Google Fit revokes the OAuth permissions and removes all the sensor registrations and recording subscriptions.

c9-fig-0010

Figure 9-10 ConfigApi.

9.3 data sub-package

The data sub-package has the fully qualified package name of com.google.android.gms.fitness.data and has about 11 classes (Figure 9-11A).

c9-fig-0011

Figure 9-11A data package.

9.3.1 Device

The Device class represents an integrated device such as a handheld device or an Android Wear device that can hold sensors. The Device class encapsulates the manufacturer and model information, which can help in identifying the source of sensor data and distinguishing between two similar sensors such as heart rate monitors on two different devices. The Device class is also useful in distinguishing between the data patterns from similar sensors on different types of devices such as accelerometer data from a smart watch versus a handheld device.

Figure 9-11B shows some of the main attributes and methods available in the Device class. There are several constants for the Device type such as TYPE_WATCH, TYPE_CHEST_STRAP, TYPE_SCALE, TYPE_PHONE, TYPE_TABLET, and TYPE_UNKNOWN.

c9-fig-0012

Figure 9-11B Device class, partial listing.

9.3.2 BleDevice

The BleDevice class represents a Bluetooth LE device that advertises information about its onboard sensors (such as heart rate monitor, step counter, and so on).

Figure 9-11C shows the BleDevice class that has methods for getting the device name, the Fit data types supported by the device, and the Bluetooth Generic Attribute Profile (GATT). More information can be found at https://developer.bluetooth.org/gatt/profiles/Pages/ProfilesHome.aspx andhttps://developer.bluetooth.org/gatt/Pages/GATT-Specification-Documents.aspx.

c9-fig-0013

Figure 9-11C BleDevice class, partial listing.

9.3.3 DataSource

A DataSource represents a unique source of sensor data and can expose the raw data that’s coming from a particular hardware sensor on the host device or a peripheral device. A DataSource can also expose data derived from merging or transforming data from other data sources.

Figure 9-11D shows the methods and attributes available in the DataSource class. A DataSource instance contains information that uniquely identifies it such as the hardware device and the App that collected or transformed the data. There can be multiple DataSources for the same DataType, which mirrors the reality that there can be multiple sensors for the same data types and fields such as heart rate, step counters, and so on.

c9-fig-0014

Figure 9-11D DataSource class, partial listing.

Apps can access the data stream from a DataSource in near real time by registering an OnDataPointListener or via making queries at periodic intervals.

9.3.4 DataType

The DataType class defines the representation of the data, which is independent of how the data was acquired, the sensor that was used, and so on. The DataType is the schema for a stream of data that can be collected and inserted into and queried from the Fit Store. A DataType contains one of more fields. Each field has a name and a format. The format indicates whether it is an int or a float denoted by FORMAT_INT_32 and FORMAT_FLOAT, respectively.

Each DataType has a unique namespaced name, for example, com.google.heart_rate.bpm is the namespaced name for the Java attribute TYPE_HEART_RATE_BPM defined in the DataType class (Figure 9-11E).

c9-fig-0015

Figure 9-11E DataType class, partial listing.

9.3.5 DataPoint

A DataPoint holds at least one field and a value representing a single data point in a data type’s stream from a particular data source (Figure 9-11F). Every DataPoint that is stored to or retrieved from Google Fit has an associated DataSource. Each DataSource in turn contains information of the sensor device and/or App that has collected or transformed the data.

c9-fig-0016

Figure 9-11F DataPoint class, partial listing.

Each DataPoint holds at least one field and the value of data, as well as a timestamp. Optionally, a Data point may also contain a start time. The exact semantics and combination of field data depends on the particular data type. Some data points represent an instantaneous reading, such as location, speed, and heart rate beats per minute. Other data points represent aggregate data, such as heart rate summary.

DataPoint instances are created by making a call to the static method DataPoint.create(), which requires a data source as the method call argument. Recall that each data source has an associated data type and each data type has associated fields.

When a DataPoint is instantiated, it contains all the appropriate l-values for the fields associated with the data type, but the r-values (values of data or content) have not been set. In other words, initially, all the “l-values” are present and the appropriate r-values and timestamp will need to be set. “l-values” represent the variable name, while “r-values” represent the content or data that’s set into a given variable (l-value). The concept of l-values and r-values is used in computer science as well as in programming languages.

The snippet below shows the setting of the r-value of a field in a DataPoint instance:

The getDataSource method returns the DataSource for the DataPoint. The call to getOriginalDataSource returns the original data source, which can—in the case of transformed or merged data—be different from the data source returned by the getDataSource method.

9.3.6 Field

The Field class represents one dimension of a data type and has a name and a format. The data type DataType.TYPE_LOCATION_SAMPLE, for example, has four fields: latitude, longitude, altitude, and accuracy.

Figure 9-11G shows the Field class with some of the static constants defined therein. The Field names are not namespaced, they are unique within the data type. Some fields such as FIELD_CONFIDENCE and FIELD_ACCURACY are secondary to their primary accompanying Field.

c9-fig-0017

Figure 9-11G Field class, partial listing.

9.3.7 Value

The Value class is a holder for a single field in a DataPoint. Depending on the DataType of the DataPoint, a Value instance is created for each Field, but it has not been set with the data (r-value). The isSet method indicates whether a value has been set on the Value instance. Figure 9-11F shows the Value class along with the DataPoint.

9.3.8 Subscription

The Subscription class encapsulates the data source and data type of a subscription (Figure 9-11H). The concept of subscription is associated with background collection of sensor data, which we covered in the section on the RecordingApi.

c9-fig-0018

Figure 9-11H Subscription class.

The Subscription class is not instantiated directly, rather the calls to the RecordingApi’s subscribe and listSubscriptions method and associated callbacks provide access to the Subscription instances that are contained within the ListSubscriptionsResult class.

9.3.9 DataSet

The DataSet represents a fixed set of DataPoints in a DataType’s stream from a particular DataSource. Typically, a DataSet contains DataPoints at fixed interval boundaries. A DataSet can be used both for batch data insertions and for reads (Figure 9-11I).

c9-fig-0019

Figure 9-11I DataSet.

The DataSet class has a static create method that needs a DataSource instance as the parameter and returns an instance of DataSet. Once you have an instance of DataSet, calling the createDataPoint method yields an instance of DataPoint. After setting values on the DataPoint instance, the DataSet’s add method facilitates adding a data point to the set. The addAll method facilitates adding multiple data point instances in one call.

9.3.10 Session

The Session class represents a workout session or period of physical activity—it has a user-visible name, a start time, a unique identifier, and some associated data. It has an associated start time that is mandatory. It also has an optional description that can be used by the user to provide some description or notes associated with the session. The Session supports storing, retrieving, and analyzing user-visible groups of data organized and aggregated in a relevant manner. A Session can be instantiated via the static inner Builder class.

Figure 9-11J shows the Session class and its inner static Builder class. Session.Builder supports the creation of Session instances. The session name and start time are mandatory fields. The identifier, description, and activity are optional. Before actually calling the build method to obtain a Session instance, you would need to call at the very least the setName and setStartTimeMillis methods—in order to ensure that the mandatory fields have been populated.

c9-fig-0020

Figure 9-11J Session class.

9.3.11 Bucket

A Bucket represents aggregate data over an interval of time using one of several possible bucketing strategies such as time interval, activity type, a session or an activity segment. Accordingly, any Bucket instance has a bucket type that can be one of TYPE_TIME, TYPE_ACTIVITY, TYPE_SESSION, or TYPE_ACTIVITY_SEGMENT. A Bucket must have a start time and an end time—for all types of Buckets. A Bucket may be setup to contain speed and heart rate summary over a time interval. A Bucket may coincide with a session, via using the bucketing strategy of TYPE_SESSION, but that does not always have to be the case.

Figure 9-11K shows the Bucket class that has no constructor or builder class. The Bucket is not instantiated by application code directly; rather, the DataReadRequest in the request sub-package has a bucketBy* family of methods in its Builder class, which allow your application to specify the particular criteria for computing the bucket. In turn, the DataReadResult from the result package has a getBucket, which facilitates access of bucket instances from the application code.

c9-fig-0021

Figure 9-11K Bucket class.

9.4 request sub-package

The request sub-package has the fully qualified package name of com.google.android.gms.fitness.request and contains about nine classes and one interface.

Figure 9-12A shows the various requests, callback, and listener available in the request sub-package.

c9-fig-0022

Figure 9-12A request sub-package.

The Google Fit API calls pertaining to Bluetooth LE scans, sensors, data sources, sessions, and so on follow an asynchronous, nonblocking mode of calls. The request sub-package has a complementary result sub-package, and individual request classes from the request sub-package typically have a corresponding result class in the result sub-package. Both the request and result sub-packages depend on the data sub-package.

9.4.1 StartBleScanRequest

The StartBleScanRequest class encapsulates a request to start a scan for a Bluetooth LE device based on the data type. The StartBleScanRequest is useful for invoking the startBleScan method available in the BleApi. The StartBleScanRequest and for that matter all the request family of classes implement the android.os.Parcelable interface.

Figure 9-12B shows the StartBleScanRequest class and its static inner Builder class. The StartBleScanRequest.Builder class allows your application to set the data types, the scan timeout, and the BleScanCallback instance in order to build an instance of the StartBleScanRequest:

c9-fig-0023

Figure 9-12B StartBleScanRequest class.

After you have created an instance of the StartBleScanRequest, you will typically invoke the startBleScan method in the BleApi, as shown in the snippet below:

9.4.2 BleScanCallback

The BleScanCallback is an abstract class that is associated with the BleApi and the StartBleScanRequest. Figure 9-12B shows the BleScanCallback and its abstract methods. Your application will need to extend this abstract class and implement the onDeviceFound and the onScanStopped methods.

9.4.3 SensorRequest

The SensorRequest class is used to request real-time data of a particular data type from a particular data source. It also lets you specify the accuracy mode, sampling rate, fastest reporting rate, delivery latency, and so on. Greater accuracy and more frequent sampling generally come at the cost of higher power consuming and faster draining of the battery. The SensorRequest class provides constants for the accuracy mode.

Figure 9-12C shows the attributes and methods of the SensorRequest class and its static inner SensorRequest.Builder class, which provides methods to build a SensorRequest instance after specifying the data source, data type, accuracy mode, sampling rate, maximum delivery latency, and so on. The delivery latency is the time delay between the time of origination of data at the sensor source and the receipt of the data update within component made the request for the data.

c9-fig-0024

Figure 9-12C SensorRequest class.

9.4.4 DataSourcesRequest

The DataSourcesRequest class represents a request to find Google Fit data sources that match specified criteria. Recall that a data source is a source of sensor data that can expose raw data from a hardware sensor or expose derived, transformed, or merged data.

Figure 9-12D shows the DataSourcesRequest and its inner static Builder class. The DataSourcesRequest is closely associated with the SensorsApi’s findDataSources method.

c9-fig-0025

Figure 9-12D DataSourcesRequest class.

9.4.5 OnDataPointListener

The OnDataPointListener interface is useful for registering for receiving live updates from a DataSource, which are delivered as DataPoints.

Figure 9-12E shows the OnDataListener interface that has one method onDataPoint. The OnDataListener is associated with the SensorApi.

c9-fig-0026

Figure 9-12E OnDataPointListener interface.

9.4.6 DataReadRequest

The DataReadRequest represents a request to read data from the Fit Store based on specified criteria and is associated with the HistoryApi. The DataReadRequest must specify at least one data source or data type and a time range. In order to request read access to aggregate data, the request should additionally specify the bucketing strategy. Recall from the section on the Bucket that the Bucket class defines Bucket types of session, activity type, activity segment, and time and contains aggregate data of one or more data types.

Figure 9-12F shows the DataRequestRequest class and its static inner Builder class, consistent with the pattern we have seen for the various other request family classes.

c9-fig-0027

Figure 9-12F DataReadRequest.

The snippet below shows an example of creating a simple DataReadRequest by setting the time range and data type using the Builder:

The HistoryApi’s readData method takes in a DataReadRequest instance as a parameter.

9.4.7 DataDeleteRequest

The DataDeleteRequest is used to specify the criteria for deleting history data. The DataDeleteRequest must specify the time interval, and it may be the data type or data source.

Figure 9-12G shows the DataDeleteRequest and its static inner Builder class.

c9-fig-0028

Figure 9-12G DataDeleteRequest.

The DataDeleteRequest’s deleteAllData method merely indicates whether all the data types are marked for deletion. This correlates to whether the Builder’s deleteAllData was invoked prior to building the DataDeleteRequest instance.

9.4.8 SessionInsertRequest

The SessionInsertRequest is used to inserting a session and associated aggregate DataPoints or DataSets into the Fit Store. The SessionInsertRequest is closely associated with the SessionsApi’s insertSession method and is useful for bulk upload of previously recorded sessions or for storing data from outside of Google Fit.

9.4.9 SessionReadRequest

The SessionReadRequest is used for reading session data from the Fit Store. The time interval and the data types are parameters that can be specified in the Builder in order to create a SessionReadRequest instance. The SessionReadRequest is closely associated with the SessionsApi’s readSession method.

9.4.10 DataTypeCreateRequest

The DataTypeCreateRequest is used for creating an application specific, custom data type in the Fit Store. Such a data type should not duplicate an existing standard/public data type. The data of this custom data type will be private to the App that created it. The data type’s name should reside in the namespace of its application’s package name. The DataTypeCreateRequest is associated with the ConfigApi’s createCustomDataType method.

9.5 result sub-package

The result sub-package contains about seven “result family” classes, each of which has a correlation with a corresponding “request family” class from the request package and/or a particular Fit API call. For instance, the DataReadResult class has a correlation with the DataReadRequest and the HistoryApi’s readData API call. The naming conventions also make such correlations between the request, result, and data quite obvious in most cases. We will be covering these result classes and their correlations individually in this section. The package summary for the result sub-package happens to list these correlations as well:

https://developer.android.com/reference/com/google/android/gms/fitness/result/package-summary.html

Figure 9-13A shows the various classes in the result package, and these classes represent the results or responses to requests and API calls. The result sub-package and the request sub-package both depend on the data sub-package. All the classes in the result package implement the Result interface from com.google.android.gms.common.api as well as the Parcelable interface, though this detail has not been depicted in the diagram.

c9-fig-0029

Figure 9-13A result package.

9.5.1 BleDevicesResult

The BleDevicesResult class represents the result of a call to the BleApi’s listClaimedBleDevice method. The BleDevicesResult class, like the other classes in the result sub-package, implements both the Result interface from the Google Play Services API’s common.api sub-package and Parcelable from the android.os package.

Figure 9-13B shows the BleDevicesResult class and its overloaded getClaimedDevices methods. It also has methods such as getStatus from the Result interface that it implements. BleDevicesResult implements both the Result and Parcelable interfaces, as do all the classes in this package. However, this detail has not been repeated in subsequent diagrams of result classes.

c9-fig-0030

Figure 9-13B BleDevicesResult class.

9.5.2 DataSourcesResult

The DataSourcesResult class is associated with the SensorApi’s findDataSources method and the DataSourcesRequest class from the request package.

Figure 9-13C shows the DataSourcesResult class and its overloaded getDataSources methods.

c9-fig-0031

Figure 9-13C DataSourcesResult class.

9.5.3 ListSubscriptionsResult

The ListSubscriptionsResult class has a correlation with the RecordingApi’s listSubscription method as well as Subscription, which in turn is associated with the data source and data type.

Figure 9-13D shows the ListSubscriptionsResult class with its getSubscriptions and overloaded getSubscriptions methods.

c9-fig-0032

Figure 9-13D ListSubscriptionsResult class.

9.5.4 DataReadResult

The DataReadResult is associated with the HistoryApi’s readData method as well as the DataReadRequest.

Figure 9-13E shows the methods available in the DataReadResult including the overloaded getDataSet method. The call to getBuckets will be relevant if the original request had specified a bucketing strategy via any of the bucketBy methods available in the DataReadRequest.Builder. The getBuckets method will return an empty list in case there is no data available or if a failure is encountered.

c9-fig-0033

Figure 9-13E DataReadResult class.

9.5.5 SessionReadResult

The SessionReadResult is associated with the SessionsApi’s readSession method and SessionReadRequest. The SessionReadResult contains the sessions and associated data that matched the criteria that were specified while building the SessionReadRequest.

Figure 9-13F shows the SessionReadResult class including its getSessions method and the overloaded getDataSet methods. The DataSet in turn contains DataPoints, which we covered in the earlier sections.

c9-fig-0034

Figure 9-13F SessionReadResult class.

9.5.6 SessionStopResult

The SessionStopResult is associated with the stopSession method available in the SessionsApi. The stopSession method requires the session identifier as a String parameter. There is no request class that correlates with the SessionStopResult.

Figure 9-13G shows the SessionStopResult class and its getSessions method that returns a list of sessions that were stopped.

c9-fig-0035

Figure 9-13G SessionStopResult class.

9.5.7 DataTypeResult

The DataTypeResult class is associated with the ConfigApi’s readDataType method, which is useful for retrieval of shareable data types or private, custom data types defined in your App. The readDataType method accepts a String parameter with the name of the data type. There is no corresponding request class associated with the DataTypeResult.

Applications require user permission in order to access a shareable data type. In case the application is missing such permission, it will need to address the received status code of FitnessStatusCodes.NEED_OUTH_PERMISSIONS by using the Activity’s startResolutionForResult, which will get the Android platform to start the appropriate Intent that will solicit the user’s consent.

Just in case an App attempts to read some other App’s custom data type—which happens to be private to the other App—the calling App will encounter an error status code of FitnessStatusCodes.INCONSISTENT_DATA_TYPE. There is no resolution for this because it is not meant to be allowed that the custom data types defined by one App are accessed by another App.

Figure 9-13H shows the DataTypeResult class that has a getDataType method. The getStatus method that the DataTypeResult class implements by virtue of implementing the Result interface has been shown only in the initial diagrams in this result series and particularly in Figure 9-13B (BleDevicesResult) in some detail.

c9-fig-0036

Figure 9-13H DataTypeResult class.

9.6 service sub-package

The Google Fit platform has built-in support for local hardware fitness sensors on Android handheld devices and Android Wear devices. The Google Fit platform also has support for peripheral Bluetooth LE (Smart) devices that support standard GATT profiles. Bluetooth LE is an interconnectivity technology that is widely used and particularly pertinent to fitness sensors and peripheral devices. Bluetooth LE however is not backward compatible with the “standard” or “classic” Bluetooth technology. And both classic Bluetooth and Bluetooth LE are themselves only one of several interconnectivity technologies for peripherals that are available today. Thus, the Google Fit platform currently provides off-the-shelf support for fitness peripheral devices, limited to those that support Bluetooth LE-based interconnectivity.

You may just possibly have the need for your Google Fit App to work with non-Bluetooth LE fitness sensors (the most obvious example of this is classic Bluetooth fitness sensors). Although this happens to be a scenario that the Google Fit platform does not address off the shelf, the service package provides the APIs that can help your App work with a sensor that does not support Bluetooth LE and expose it to the Google Fit platform. Once exposed as a software sensor-based Google Fit sensor, from that point forward, it can be accessed via the standard SensorsApi.

In another scenario, your application’s algorithm can analyze and interpret raw sensor data from an Android device’s accelerometer or image data from an Android device’s camera, in order to implement a software-based step counter or a heart rate monitor, respectively. With the human finger placed on a phone’s camera for instance, the image data captured over a period of say 1 minute can be analyzed and interpreted to determine a heart rate reading—microscopic movements of the finger cause patterns of color changes in a repeating cycle, the periodicity of which if interpreted correctly will tend to coincide with the heart rate. We have covered computer vision-based sensors in Chapter 2. The raw data in such cases does not directly constitute fitness data, but the software-based algorithm can analyze and interpret such raw data to compute or infer fitness data readings such as the heart rate and more. This is another scenario that the Google Fit platform does not support off the shelf; however, service package’s API can be useful to expose such software application-based sensor data to the Google Fit platform.

Thus, the service sub-package will be useful for implementing third-party software-based sensors that are exposed to and compatible with the Google Fit platform in scenarios such as:

  1. You would like your Google Fit App to support a fitness sensor hardware device that uses a connectivity technology other than Bluetooth LE and expose such data to the Google Fit platform.
  2. You would like to write a software-based sensor that uses more fundamental, raw sensor, or image data to compute fitness data and expose such data to the Google Fit platform.

Chapter 5 covered several interconnectivity and discovery technologies that have a correlation with implementing custom software sensors. Just in case you had skipped that chapter and are interested in exploring implementing a custom third-party Google Fit sensor, now is a good time to revisit Chapter 5.

If you already have live sensor data that is compatible off the shelf with the Google Fit platform, you will be less likely to need to implement your own software-based sensor.

Figure 9-14 shows the FitnessSensorService and FitnessSensorServiceRequest classes and the one interface in the service sub-package.

c9-fig-0037

Figure 9-14 service sub-package.

9.6.1 FitnessSensorService

The FitnessSensorService helps your application to expose a software-based sensor to the Google Fit platform. After that, other Apps can claim the software-based sensor “device” and use it via the SensorsApi’s standard interfaces.

The FitnessSensorService is abstract and extends the abstract android.app.Service. Your application’s service implementation will need to extend FitnessSensorService and implement the abstract methods including onFindDataSources, onRegister, and onUnregister from the FitnessSensorService hierarchy as well as the onBind and life cycle methods from the Service hierarchy. Registration is on the basis of the data source. As long as there is an active registration for a data source, your service must publish DataPoints at the requested sampling rate and batch interval using the dispatcher.

Your service will naturally need an entry in the application’s AndroidManifest.xml. The exported flag will need to be set to true as it is expected to be exposed to the Google Fit platform and interact with external Apps. Furthermore, the service’s entry in the manifest will need to declare a mime type filter based on the Google Fit data type (standard or shareable) that it supports. Below is a snippet of such an entry in the AndroidManifest.xml file:

The Google Fit platform will bind to your service and remain bound as long as there is an active registration or subscription for the sensor service. The Google Fit platform manages the life cycle of your service.

9.6.2 FitnessSensorServiceRequest

The FitnessSensorRequest encapsulates the request for registering for sensor events from your service implementation, which includes the data source, batch interval, sampling rate, and dispatcher to publish data to. You will notice that the FitnessSensorServiceRequest does not have any Builder and does not reside in the request package along with the request family classes that we covered earlier. Apps that are interested in receiving sensor data do not instantiate or use the FitnessSensorServiceRequest, rather they use the SensorApi in the standard way. The Google Platform acts as the intermediary between Apps that desire to subscribe to data sources, and this is achieved via the intent-filter mechanism declared in the manifest.

9.6.3 SensorEventDispatcher interface

The SensorEventDispatcher is used by the FitnessSensorService implementation to dispatch or push events out to the Google Fit platform. Your implementation of the FitnessSensorService is the intermediary between the sensor and the Google Fit platform. The publish methods in the SensorEventDispatcher help your service publish individual DataPoints as well as a batch of DataPoints.

References and Further Reading

  1. https://developers.google.com/fit/
  2. https://developers.google.com/fit/android/reference
  3. http://developer.android.com/reference/com/google/android/gms/fitness/package-summary.html
  4. https://developers.google.com/fit/android/data-type
  5. http://tools.ietf.org/html/rfc6749
  6. http://en.wikipedia.org/wiki/Value_(computer_science)
  7. http://developer.android.com/reference/com/google/android/gms/common/api/Result.html
  8. http://developer.android.com/reference/com/google/android/gms/common/api/Status.html
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.137.17