Search code examples
androidgoogle-fit

Handle GoogleFit in background in Android App


I am trying to connect my app to Google Fit. I am using an IntentService that needs to do the following things. Gets started when I have information about steps. At this point I am trying to create the GoogleApiClient by calling the following code:

mClient = new GoogleApiClient.Builder(this)
      .addApi(Fitness.HISTORY_API)
      .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
      .addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
      .addConnectionCallbacks(
            new GoogleApiClient.ConnectionCallbacks() {
               @Override
               public void onConnected(Bundle bundle) {
                  log.info("FITNESS_API: Connected!!!");
                  Thread thread = new Thread(new Runnable() {
                     @Override
                     public void run() {
                        insertOrUpdateDataPoints();
                     }
                  });

                  thread.start();
               }

               @Override
               public void onConnectionSuspended(int i) {
                  // If your connection to the sensor gets lost at some point,
                  // you'll be able to determine the reason and react to it here.
                  if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
                     log.info("FITNESS_API: Connection lost.  Cause: Network Lost.");
                  } else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
                     log.info("FITNESS_API: Connection lost.  Reason: Service Disconnected");
                  }
               }
            }
      ).build();

mClient.connect();

After creating a DataSet and adding the steps details as DataPoint elemnets, I sync the information to Google Fit and close the GoogleApiClient with:

com.google.android.gms.common.api.Status insertStatus =
  Fitness.HistoryApi.insertData(mClient, dataSet).await(1, TimeUnit.MINUTES);

  // Before querying the data, check to see if the insertion succeeded.
  if (!insertStatus.isSuccess()) {
     log.info("FITNESS_API: There was a problem inserting the dataset. Status = " + insertStatus.getStatusCode());
  }

  mClient.disconnect();
  mClient = null;

The problem is that by trying to manage the GoogleApiClient on my own (without enableAutoManage), I don't get prompted to allow the app to post data to Google Fit. This behaviour changes if I use enableAutoManage when creating the GoogleApiClient. However, in order to enableAutoManage for the client, I need to have a ActivityFragment due to the parameters required by enableAutoManage. I don't have access to an ActivityFragment in the IntentyService and I do want to keep the management of the client and the insert action in a separate service which can run in the background.

Also when I don't use enableAutoManage even though I have registered the connect callback for the GoogleApiClient nothing happens.

How can I ensure that my application prompts the user to allow the app to post to Google Fit? I need this to happen if the app doesn't have permission to post in Google Fit when the user opens the app. Any ideas? Thank you.


Solution

  • I have found the solution.

    If you don't want to use "enableAutoManage", you need to register onConnectionFailed method like this:

        @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if( !authInProgress ) {
            try {
                authInProgress = true;
                connectionResult.startResolutionForResult( MainActivity.this, REQUEST_OAUTH );
            } catch(IntentSender.SendIntentException e ) {
    
            }
        } else {
            Log.e( "GoogleFit", "authInProgress" );
        }
    }
    

    This will present the dialog.