Multiple instance of GoogleApiClient - android

Context
When my app is launched for the first time, it asks the user to connect to Google Fit and in the next step (another activity), he has the possibility to connect to Google Plus.
When I accepted to connect to both APIs, once in my app, I have the possibility to disconnect from Fit or Plus, but, I don't know why, it is impossible to disconnect from Fit when the Plus client is connected and if I disconnect from Plus, it works well, but the Fit client gets also disconnected.
When the app is launched, if I decide to connect only to Fit and not Plus, it works as expected, I mean I can disconnect correctly from Fit.
Question
I thought that it was possible to have multiple instances of GoogleApiClient, but I have the impression that both clients are "connected".
Is there a kind of hierarchy between the API clients?
Edit
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
/**
* Create the fitness client - this is mandatory to use the app
*/
buildFitnessClient();
/**
* Get the result of Google Plus connection
*/
// If skip button is clicked, the user does not want to connect to G+
Boolean isSkipClicked = getSharedPreferences("ISSKIPCLICKED", MODE_PRIVATE).getBoolean("isSkipClicked", false);
if(isSkipClicked){
// The user has the possibility to connect to G+ through the menu
}
// else, the user is connected to G+, rebuilt the client
else{
buildPlusClient();
mPlusClient.connect();
}
}
The buildFitnessClient() :
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.RECORDING_API)
.addApi(Fitness.CONFIG_API)
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addScope(new Scope((Scopes.FITNESS_NUTRITION_READ_WRITE)))
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected to Fitness API!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
mClient.connect();
}
#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.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed. Cause: " + result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(),
Main2Activity.this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization dialog is displayed to the user.
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(Main2Activity.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
}
}
)
.build();
}
The buildPlusClient method:
public void buildPlusClient(){
/**
* Handle the connection to Google Plus client
*/
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestProfile()
.build();
GoogleApiClient.OnConnectionFailedListener unresolvedConnectionFailedListener = new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed:" + connectionResult);
}
};
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mPlusClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, unresolvedConnectionFailedListener /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
}
Below, methods to disconnect from Gplus and/or Gfit:
private void signOutFit(){
if(mClient.isConnected()){
Fitness.ConfigApi.disableFit(mClient)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
//Log.d(TAG, "Disconnect success");
Toast.makeText(Main2Activity.this,"Disconnected from Google Fit",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(Main2Activity.this,"Impossible to disconnect from Fit",Toast.LENGTH_SHORT).show();
}
}
});
}
}
private void signOutPlus(){
if(mPlusClient.isConnected()){
Auth.GoogleSignInApi.signOut(mPlusClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if(status.isSuccess()){
Toast.makeText(Main2Activity.this, "Disconnect from Google Plus", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(Main2Activity.this, "Impossible to disconnect from Google Plus", Toast.LENGTH_SHORT).show();
}
}
});
}
}

Related

How can I get Google Fit Client state?

At some devices, I get data once in an hour! But at another, I get them every 4 minutes.
I make client:
client = new GoogleApiClient.Builder(context)
.addApi(Fitness.SENSORS_API)
.addScope(Fitness.SCOPE_ACTIVITY_READ)
.addScope(Fitness.SCOPE_BODY_READ_WRITE)
.addScope(Fitness.SCOPE_LOCATION_READ_WRITE)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ))
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addConnectionCallbacks(Client.this)
.addOnConnectionFailedListener(Client.this)
.build();
client.connect();
Then sensor:
Fitness.SensorsApi.add(
client,
new SensorRequest.Builder()
.setDataSource(dataSource)
.setDataType(dataType)
.setAccuracyMode(SensorRequest.ACCURACY_MODE_HIGH)
.setSamplingRate(5, TimeUnit.SECONDS)
.setFastestRate(1, TimeUnit.SECONDS)
.setMaxDeliveryLatency(20, TimeUnit.SECONDS)
.build(),
mListener)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.d("stepsCount", "Listener registered!");
} else {
Log.d("stepsCount", "Listener not registered.");
}
}
});
And then I want to check client state, but I don't know how (
You can always check the state with the callback given in the document:
private void buildFitnessClient() {
if (mClient == null && checkPermissions()) {
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
findFitnessDataSources();
}
#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 == ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i
== ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG,
"Connection lost. Reason: Service Disconnected");
}
}
}
)
.enableAutoManage(this, 0, new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Google Play services connection failed. Cause: " +
result.toString());
Snackbar.make(
MainActivity.this.findViewById(R.id.main_activity_view),
"Exception while connecting to Google Play services: " +
result.getErrorMessage(),
Snackbar.LENGTH_INDEFINITE).show();
}
})
.build();
}
}
Now for some information on how to show the data in your app in real time, using the Sensors API together with the Recording API.
DevBytes: Google Fit APIs for Android - Setup and Sensors
DevBytes: Google Fit APIs for Android - Recording and History
Hope it helps!

Reading weight with Google Fit

I can connect to Google Fit and read weight data but not all the data that I can see in Google Fit Web. I believe that something is wrong with datasources but I'm not sure. The code for reading is:
Instant endTime = Instant.now();
Instant startTime = DateTime.now().minusYears(10).toInstant();
DataReadRequest readRequest = new DataReadRequest.Builder ()
.setTimeRange (startTime.getMillis(), endTime.getMillis(), TimeUnit.MILLISECONDS)
.read (DataType.TYPE_WEIGHT)
.build ();
DataReadResult dataReadResult = Fitness.HistoryApi.readData(MyApp.mClient, readRequest).await (1, TimeUnit.MINUTES);
https://developers.google.com/fit/rest/v1/authorization#OAuth2Authorizing
DataType.TYPE_WEIGHT must be authorized by an authenticated Scopes.FITNESS_BODY_READ
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.HISTORY_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_BODY_READ))
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs. What to do?
// Look at some data!!
new InsertAndVerifyDataTask().execute();
}
#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 == ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
}
)
.enableAutoManage(this, 0, new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Google Play services connection failed. Cause: " +
result.toString());
Snackbar.make(
MainActivity.this.findViewById(R.id.main_activity_view),
"Exception while connecting to Google Play services: " +
result.getErrorMessage(),
Snackbar.LENGTH_INDEFINITE).show();
}
})
.build();

Download DriveFIle on server

I have an Android application where my user can select a document to upload and on my server I want to pass the URL that can be used to download the file. I'm basing much of my code on this:
http://www.101apps.co.za/index.php/articles/android-apps-and-google-drive-picking-files.html
and I'm also using these guidelines to download the file:
https://developers.google.com/drive/web/manage-downloads
Problem i'm facing is that the getWebContentLink method is returning null every time. I'm not able to download the file ever on my server (even with the OAuth 2.0 client ID). Is there something i'm missing here?
I'm able to getAlternateLink URL but that is only for viewing the document on a browser, which is not what I want. I have some of my relevant methods below:
public GoogleApiClient getGoogleApiClient() {
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
return mGoogleApiClient;
}
// Google Drive call back
public void onConnected(Bundle bundle) {
if (getGoogleApiClient().isConnected()) {
getDataFromGoogleDrive();
}
}
public void onConnectionSuspended(int i) {
}
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(getActivity(), GDRIVE_CONNECTION_REQUEST);
} catch (Exception e) {
AlertUtil.showOkAlert(getActivity(), "Oops", "We were unable to connect to your Google Drive.");
}
} else {
GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), getActivity(), 0).show();
}
}
private void getDataFromGoogleDrive() {
try {
IntentSender intentSender = Drive.DriveApi.newOpenFileActivityBuilder().build(getGoogleApiClient());
getActivity().startIntentSenderForResult(intentSender, GDRIVE_FILE_REQUEST, null, 0, 0, 0);
} catch (Exception e) {
Log.w(TAG, "ERROR connecting!", e);
getGoogleApiClient().connect();
}
}
My goal is to allow my user to select a file on the app and then have the server download the file.
I was able to do it this way:
// accountName is the email address that was chosen
token = GoogleAuthUtil.getTokenWithNotification(fragment.getActivity(), accountName, scope, null);
Once you get a token you can make requests as per this page:
https://developers.google.com/drive/web/manage-downloads
The token for Authorization header is above and the resourceId you can get from DriveId.

OnDataPointListener does not get callback if GoogleApiClient is disconnected

I am using Google Fit APIs for the first time. I have modified the BasicSensorsApi sample code to calculate steps count. It is working fine, but the problem is when I call GoogleApiClient.disconnect() in onStop() function and then again call GoogleApiClient.connect() in onStart() function, OnDataPointListener stops getting callbacks. I am not unregistering this listener any where.
When I don't call GoogleApiClient.disconnect() it is working fine and I get callbacks event after activity's onStop() function is called.
I am not sure whether I should disconnect GoogleApiClient in onStop() function or not. If yes then how can I solve above problem?
Here is the relavent code:
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ))
.addScope(new Scope((Scopes.FITNESS_ACTIVITY_READ)))
.addScope(new Scope((Scopes.FITNESS_BODY_READ)))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
findFitnessDataSources();
}
#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.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed. Cause: " + result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), MainActivity.this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization dialog is displayed to the user.
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(MainActivity.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
}
}
)
.build();
}
#Override
protected void onStart() {
super.onStart();
// Connect to the Fitness API
Log.i(TAG, "Connecting...");
mClient.connect();
}
#Override
protected void onStop() {
super.onStop();
if (mClient.isConnected()) {
//mClient.disconnect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mClient.isConnecting() && !mClient.isConnected()) {
mClient.connect();
}
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(AUTH_PENDING, authInProgress);
}
// [END auth_connection_flow_in_activity_lifecycle_methods]
/**
* Find available data sources and attempt to register on a specific {#link DataType}.
* If the application cares about a data type but doesn't care about the source of the data,
* this can be skipped entirely, instead calling
* {#link com.google.android.gms.fitness.SensorsApi
* #register(GoogleApiClient, SensorRequest, DataSourceListener)},
* where the {#link SensorRequest} contains the desired data type.
*/
private void findFitnessDataSources() {
// [START find_data_sources]
Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder()
// At least one datatype must be specified.
.setDataTypes(DataType.TYPE_STEP_COUNT_CADENCE)
.setDataTypes(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.setDataTypes(DataType.TYPE_STEP_COUNT_DELTA)
// Can specify whether data type is raw or derived.
.setDataSourceTypes(DataSource.TYPE_DERIVED)
.build())
.setResultCallback(new ResultCallback<DataSourcesResult>() {
#Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.i(TAG, "Result: " + dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.i(TAG, "Data source found: " + dataSource.toString());
Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());
//Let's register a listener to receive Activity data!
if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CADENCE) && mListener == null) {
Log.i(TAG, "Data source for TYPE_STEP_COUNT_CADENCE found! Registering.");
registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_CADENCE);
} else if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_CUMULATIVE) && mListener == null) {
Log.i(TAG, "Data source for TYPE_STEP_COUNT_CUMULATIVE found! Registering.");
registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_CUMULATIVE);
} else if (dataSource.getDataType().equals(DataType.TYPE_STEP_COUNT_DELTA) && mListener == null) {
Log.i(TAG, "Data source for TYPE_STEP_COUNT_DELTA found! Registering.");
registerFitnessDataListener(dataSource, DataType.TYPE_STEP_COUNT_DELTA);
}
}
}
});
// [END find_data_sources]
}
/**
* Register a listener with the Sensors API for the provided {#link DataSource} and
* {#link DataType} combo.
*/
private void registerFitnessDataListener(DataSource dataSource, DataType dataType) {
// [START register_data_listener]
mListener = new OnDataPointListener() {
#Override
public void onDataPoint(DataPoint dataPoint) {
for (Field field : dataPoint.getDataType().getFields()) {
Value val = dataPoint.getValue(field);
Log.i(TAG, "Detected DataPoint field: " + field.getName());
Log.i(TAG, "Detected DataPoint value: " + val);
}
}
};
Fitness.SensorsApi.add(
mClient,
new SensorRequest.Builder()
.setDataSource(dataSource) // Optional but recommended for custom data sets.
.setDataType(dataType) // Can't be omitted.
.setSamplingRate(10, TimeUnit.SECONDS)
.build(),
mListener)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG, "Listener registered!");
} else {
Log.i(TAG, "Listener not registered.");
}
}
});
// [END register_data_listener]
}
If you are tracking the step counts in the foreground then this is correct behaviour as you are disconnecting the google api client in onstop(). Once GoogleApiClient is disconnected all the listeners will be removed from the GoogleApiClient. But if you wish to track the step counts in the background, then you may have to move your implementation to a service and decide when exactly you want to disconnect from GoogleApiclient.
contrary to the documentation, you have to disconnect in onDestroy not in onStop. connect in onCreate and do nothing in onStop/onStart.
Why?
because an app waiting for onConnect to be called does not prevent onStop being called. What happens is that onStop is called before your app receives the event. then, of course, it disconnects and never gets it.

Multiple GoogleApiClient not firing connect()

TL;DR; GoogleFit Api client does not connect if is signed in with Google+
So... I'm facing a problem when using GoogleFit and Google+ api together. I am using Google+ to sign in a user and using GoogleFit to retrieve fitness.
Besides Google+ I have several other login options such as Facebook and Twitter. My problem is that if a user is signed in with Google+ the user can no longer connect to the Google Fit client. Basically when the button to connect to GoogleFit is pressed nothing happens.
IF the user authenticates with Facebook or Twitter the GoogleFit client can connect just fine...
Here are some relevant code from this activity:
Google+ client:
private GoogleApiClient buildGoogleApiClient() {
return new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.addScope(Plus.SCOPE_PLUS_PROFILE)
.build();
}
Google Fit client, this method is called whenever the user press the button to link GoogleFit to the app:
public void buildFitnessClient(Button b) {
// Create the Google API Client
fitConnectButton = b;
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mClient.connect();
}
Lifecycle stuff:
#Override
public void onConnected(Bundle bundle) {
mSignInClicked = false;
if(mGoogleServices != null) {
Plus.PeopleApi.loadVisible(mGoogleServices, null).setResultCallback(this);
userData = getProfileInformation();
}
if (hasWearDevice) mClient.connect();
}
#Override
protected void onStart() {
super.onStart();
// Connect to G+ api
if(mGoogleServices != null) mGoogleServices.connect();
// Connect to the Fitness API
if (hasWearDevice) mClient.connect();
}
#Override
public void onStop() {
super.onStop();
if(mGoogleServices != null) {
if(mGoogleServices.isConnected()) mGoogleServices.disconnect();
}
if(hasWearDevice) {
if(mClient.isConnected()) mClient.disconnect();
}
}
Any suggestions?
It's not a solution but a suggestion (I can't comment).
Maybe the problem comes from that you can be only be connected with GoogleApiClient only one time.
You are connected with Google+ scope and so when you try to connect with Fit scope it could not work because you are already connected.
Maybe you can use two types of connection :
One with Google Plus only
One with Google Plus AND Google Fit scope.
It could be like this :
mClient = new GoogleApiClient.Builder(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.addScope(Plus.SCOPE_PLUS_PROFILE)
.addApi(Fitness.API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Hope it could help....
I ended up solving my problems by using different callback and connectionFailed listeners for each one of the clients.
My builder for the GoogleFitClient ended up looking like this:
public void startFitnessClient() {
mGoogleFitClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
if (hasWearDevice) mGoogleFitClient.connect();
}
#Override
public void onConnectionSuspended(int i) {
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(LOG_TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(LOG_TAG, "Connection lost. Reason: Service Disconnected");
}
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization dialog is displayed to the user.
if (!authInProgress) {
try {
Log.i(LOG_TAG, "Attempting to resolve failed connection");
authInProgress = true;
connectionResult.startResolutionForResult(BaseActivity.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(LOG_TAG, "Exception while starting resolution activity", e);
Crashlytics.logException(e);
}
}
}
})
.build();
}
And this is my client for the Google+ client.
private void buildGoogleApiClient() {
mGooglePlusClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
mSignInClicked = false;
if(mGooglePlusClient != null) {
Plus.PeopleApi.loadVisible(mGooglePlusClient, null).setResultCallback(BaseActivity.this);
userData = getProfileInformation();
}
}
#Override
public void onConnectionSuspended(int i) {
mGooglePlusClient.connect();
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
mConnectionResult = connectionResult;
if (!connectionResult.hasResolution()) {
GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(), BaseActivity.this, 0).show();
return;
}
if (!mIntentInProgress) {
if (mSignInClicked) {
resolveSignInError();
}
}
}
})
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.addScope(Plus.SCOPE_PLUS_PROFILE)
.build();
}
For what I observed by Logging every step of the process while debugging is that the authentication intent call happens inside onConnectionFailed with the call to startResolutionForResult and when they were sharing the same callback listeners once the Google+ client was connected that callback was never made by the GoogleFit client. By splitting both of them it's being guarantee that they are being called now.

Categories

Resources