Time for action – recording fitness data in background using Recording API

The Recording API allows your app to request automated storage of sensor data in a battery-efficient manner by creating subscriptions. Once you add a subscription for a data type, then it's Google Play services' responsibility to start recording the data for the requested data type in the background. This recorded data is stored in the Google fitness store and can be queried by History API. The Recording API only decides which data type to record; everything else is managed by the Google fitness platform. The Recording API is part of Google play services. The steps for connecting to Google play services via the GoogleApiClient class are exactly the same as for the Sensors API, discussed in the previous section. In our example, inside SubscriptionActivity we will perform four important tasks with subscriptions. First, we will get authorization to read history data from the fitness store using the History API. Second, we will list all the existing subscriptions. Third, we will add subscriptions from the spinner drop-down. Finally, we will delete an already added subscription. Now let's look at the individual tasks performed by SubscriptionActivity.

  1. The first task performed by SubscriptionActivityis to get authorization from the user to read history fitness data using the History API. This authorization has to be requested for the first time only. The code and process for getting authorization is exactly the same as for Sensors API, which we discussed in the previous section. The only difference is that we have to add RECORDING_API in place of SENSORS_API in the addApi() method of the GoogleApiClient class.Even though authorization has already been given in the SensorActivity class, we still have to get authorization for two reasons: we are using a different API (History API) and the user might go directly to SubscriptionActivity instead of going to SensorActivity first. The code used inSubscriptionActivity can be downloaded from the code bundle for this chapter:
            public class SubscriptionActivity extends Activity 
            implements ConnectionCallbacks, 
            OnConnectionFailedListener, OnItemSelectedListener, 
            OnItemClickListener { 
     
              @Override 
              protected void onCreate(Bundle savedInstanceState) { 
                super.onCreate(savedInstanceState); 
                setContentView(R.layout.subscriptiondata_layout); 
     
                mClient = new GoogleApiClient.Builder(this) 
                .addApi(Fitness.RECORDING_API)          
                .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ)) 
                .addScope(new Scope(Scopes.FITNESS_BODY_READ)) 
                .addScope(new Scope(Scopes.FITNESS_LOCATION_READ)) 
                .addScope(new 
                Scope(Scopes.FITNESS_NUTRITION_READ)) 
                .addConnectionCallbacks(this) 
                .addOnConnectionFailedListener(this).build(); 
                setUpSpinnerDropDown(); 
                setUpListView(); 
            } 
    
  2. The second task performed by SubscriptionActivityis to list all the existing active subscriptions. We show the entire active subscriptions list of the data type in the ListView, which is set up inside the setUpListView() method (this method is the same as in the previous SensorActivity class) and is called from the onCreate() method of the activity. As soon as we get connected to the Google play services through the GoogleApiClient object, we call the listExistingSubscription()method to get the list of active subscriptions. Inside the listExistingSubscription()method, we use the listSubscriptions() method of Recording API to get the list of all active subscriptions asynchronously inside the object of ResultCallback<ListSubscriptionsResult>, which is set using the setResultCallback() method of the API. We receive a list of Subscription objects, which contains all the details of the active subscription. To display the results in the ListView, we only take the data type of the subscription and add it to the mDataTypeList, which acts a source for the ListView. We set the item click listener on the ListView to receive the clicked subscription item index. The implementation details of ListAdapter can be found in the code that comes with this chapter:

            @Override 
            public void onConnected(Bundle bundle) { 
     
              listExistingSubscription(); 
            } 
     
            public void listExistingSubscription() { 
     
              Fitness.RecordingApi.listSubscriptions(mClient) 
              setResultCallback(new 
              ResultCallback<ListSubscriptionsResult>() { 
                @Override 
                public void onResult(ListSubscriptionsResult 
                listSubscriptionsResult) { 
                  mDataTypeList.clear(); 
                  for (Subscription sc : 
                  listSubscriptionsResult.getSubscriptions()) { 
                    mDataTypeList.add(sc.getDataType()); 
                  } 
                  runOnUiThread(new Runnable() { 
                    @Override 
                    public void run() { 
                      mListAdapter.notifyDataSetChanged(); 
                    } 
                  }); 
                } 
              }); 
            } 
    
  3. The third important task performed by SubscriptionActivityis to add subscriptions. We can add subscriptions based either on a data source or a data type. For our example, we add it using a data type. We use the spinner drop-down to let the user select a particular data type. In the setUpSpinnerDropDown() method (this method is the same as in the previous SensorActivity class) we set up the spinner and set its selected listener. We get all the human readable strings values for all the available data types from the getDataTypeReadableValues() method of the DataHelper utility singleton class. After the user has selected a data type from the spinner drop-down value, we add the subscription for that particular data type. In the onItemSelected() spinner callback, we get the selected item position and by using the getDataTypeRawValues() method of the DataHelper utility class, we get its corresponding DataType object value, which is then passed to the addSubscription() method for adding a subscription. Inside the addSubscription()method, we use the subscribe()method of Recording API to add the subscription. Once the subscription is successfully added, then we refresh the active subscription list by calling the listExistingSubscription() method:

            @Override 
            public void onItemSelected(AdapterView<?> parent, View 
            view, int position, long id) { 
     
              if(position!=0 && mClient.isConnected()) { 
                addSubscription(DataHelper.getInstance()
                .getDataTypeRawValues().get(position)); 
              } 
            } 
     
            public void addSubscription(DataType mDataType) { 
         
              Fitness.RecordingApi.subscribe(mClient, mDataType) 
              .setResultCallback(new ResultCallback<Status>() { 
                @Override 
                public void onResult(Status status) { 
                  if (status.isSuccess()) { 
                    listExistingSubscription(); 
                  } else { 
                   Log.i(TAG, "There was a problem subscribing."); 
                  } 
                } 
              }); 
            } 
    
  4. The fourth and final task performed by SubscriptionActivityis to remove any active subscriptions. This is done by taking the clicked index of displayed active subscription data types on ListView inside onItemClick() and sending the corresponding data type to the removeSubscription() method. Inside the removeSubscription() method, we use the unsubscribe() method of Recording API to remove the active subscription. The unsubscribe() API accepts the object of the GoogleApiClient class and the data type to be removed. Once the subscription has been removed successfully, we remove the subscribed data type from mDataTypeList and refresh the ListView:
        @Override 
        public void onItemClick(AdapterView<?> parent, View 
        view, int position, long id) { 
 
          removeSubscription(mDataTypeList.get(position)); 
        } 
 
        public void removeSubscription(DataType mDataType) { 
     
          Fitness.RecordingApi.unsubscribe(mClient, mDataType) 
          .setResultCallback(new ResultCallback<Status>() { 
            @Override 
            public void onResult(Status status) { 
              if (status.isSuccess()) { 
                runOnUiThread(new Runnable() { 
                  @Override 
                  public void run() { 
                    mDataTypeList.remove
                    (lastRemovedPosition); 
                    mListAdapter.notifyDataSetChanged(); 
                  } 
                }); 
              } else { 
                Log.i(TAG, "Failed to unsubscribe "); 
              } 
            } 
          }); 
        } 

What just happened?

In the SubscriptionActivity, we developed a utility that deals with all the operations (adding, removing, listing) for subscriptions. Subscriptions are really helpful when you don't want your application to manage the collection and storage of fitness data by staying in the background forever. All subscribed data is collected and stored in the Google Fitness Store and can be retrieved using History API, which we will discuss in the next section. The following is a screenshot from a Nexus 5X device showing the list of active subscriptions:

What just happened?

..................Content has been hidden....................

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