7

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.

Vlad Bogdan
  • 700
  • 1
  • 8
  • 25

3 Answers3

1

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.

Vlad Bogdan
  • 700
  • 1
  • 8
  • 25
0

In your intent service use the above method mentioned by @Vlad. Create a notification(Sticky or otherwise depending on your importance) asking user to give you permission when onconnection failed is encountered. The notification will redirect user to an activity where you ask user to give you fitaccess again.

wittyurchin
  • 301
  • 5
  • 7
0
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_OAUTH:
            if (resultCode != Activity.RESULT_OK) {
                return;
            }

            if (!googleApiClient.isConnected()) {
                googleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
            } else {
                readDataTask();
            }
            return;
        case RC_SIGN_IN:
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                GoogleSignInAccount account = result.getSignInAccount();
                String email = account.getEmail();//you can get OAuth user's email AT THIS POINT.

                if (GoogleFitService.googleApiClient.isConnected()) {
                    readDataTask();
                }
            }
    }
}

First time what you have to DO is Oauth Goole accout, then get your's email.

 gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .setAccountName("user's email")
                .requestScopes(
                        new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE),
                        new Scope(Scopes.FITNESS_BODY_READ_WRITE),
                        new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE),
                        new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
                .build();

when you get Google Fit data at background, you need to set Email.

user3627060
  • 21
  • 1
  • 3