I've started creating Watch Face for Android Wear. I've implemented almost everything and now I want to show on the face the phone battery. From what I understood after my research this is only doable via Message or Data Layer API. So I've started working in his area but I'm facing a problem in the very beginning. I cannot connect to Google Api Client.
I have two classes under "wear" - one generic for the watch (service) and one created by me:
public class BatteryActivity extends Activity {
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks( new ConnectionCallbacks() {
#Override
public void onConnected(Bundle connectionHint) {
Log.i( "", "onConnected: " + connectionHint);
// Now you can use the Data Layer API
}
#Override
public void onConnectionSuspended(int cause) {
Log.i( "", "onConnectionSuspended: " + cause);
}
})
.addOnConnectionFailedListener( new OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i( "", "onConnectionFailed: " + result);
}
})
// Request access only to the Wearable API
.addApi(Wearable.API)
.build();
}
Whan I simply instance it like this: BatteryActivity batteryActivity = new BatteryActivity();
I get this error:
java.lang.NullPointerException: Attempt to invoke virtual method
'android.os.Looper android.content.Context.getMainLooper()' on a null
object reference
I don't understand how mGoogleApiClient is null if I've instance it.
As a note - this is purely based on google documentation here - https://developer.android.com/training/wearables/data-layer/messages.html
I suppose you should build the GoogleApiClient on onCreate method. Your code would be like this:
public class BatteryActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks( new ConnectionCallbacks() {
#Override
public void onConnected(Bundle connectionHint) {
Log.i( "", "onConnected: " + connectionHint);
// Now you can use the Data Layer API
}
#Override
public void onConnectionSuspended(int cause) {
Log.i( "", "onConnectionSuspended: " + cause);
}
})
.addOnConnectionFailedListener( new OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i( "", "onConnectionFailed: " + result);
}
})
// Request access only to the Wearable API
.addApi(Wearable.API)
.build();
}
}
It also happens when not providing proper context. Pass context like this :
mGoogleApiClient = new GoogleApiClient.Builder(context) // Pass context here
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
Ideally this should be done via Async task: https://developer.android.com/google/auth/api-client.html#Communicating
private class WatchTask extends AsyncTask<String, Void, Void> {
protected void doInBackground(String text) {
Or for a quick fix, you may just be using this in the wrong spot:
In your onCreate use getActivity() or this to use a Context for this line:
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
I would also suggest checking out: http://developer.android.com/training/wearables/data-layer/index.html
If you really want to use an activity, then it would look something like:
public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, MessageApi.MessageListener {
private GoogleApiClient googleClient; // A google client for Wear interaction
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Build a new GoogleApiClient that includes the Wearable API
googleClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
#Override
public void onConnected(Bundle connectionHint) {
Wearable.MessageApi.addListener(googleClient, this);
}
#Override
public void onMessageReceived(MessageEvent messageEvent) {
//Same onMessageReceived as in WearableListenerService
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) { }
#Override
public void onConnectionSuspended(int i) { }
}
Related
I am running a background job to re-register Geofences when they've expired.
The code gets triggered fine. The notification is getting fired in onPostExecute, but the code inside the setResultCallback is never being accessed.
How should I enable that callback so the PlaceBuffer object can be sent to the geofencing class, and therefore, get added and registered?
#Override
public boolean onStartJob(final JobParameters job)
{
mBackgroundTask = new AsyncTask<Object, Void, List<String>>()
{
#Override
protected List<String> doInBackground(Object... params)
{
Context context = GeofenceRegistrationFirebaseJobService.this;
// get all places in the database
Uri uri = PlaceContract.PlaceEntry.CONTENT_URI;
Cursor cursor = context.getContentResolver().query(
uri,
null,
null,
null,
null);
if (cursor == null || cursor.getCount() == 0) return null;
List<String> placesIds = new ArrayList<>();
cursor.moveToPosition(-1);
while (cursor.moveToNext())
{
placesIds.add(cursor.getString(cursor
.getColumnIndex(PlaceContract.PlaceEntry.COLUMN_PLACE_ID)));
}
cursor.close();
return placesIds;
}
#Override
protected void onPostExecute(List<String> placesIds)
{
Context context = GeofenceRegistrationFirebaseJobService.this;
// Build up the LocationServices API client
googleApiClient= new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addApi(Places.GEO_DATA_API)
.build();
geofencing = new Geofencing(context, googleApiClient);
PendingResult<PlaceBuffer> placeResult =
Places.GeoDataApi.getPlaceById(googleApiClient,
placesIds.toArray(new String[placesIds.size()]));
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>()
{
#Override
public void onResult(#NonNull PlaceBuffer places)
{
geofencing.addUpdateGeofences(places);
geofencing.registerAllGeofences();
}
});
// when the job is finished, issue a notification if is set in preferences
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
// does user have notifications enabled?
boolean wantNotif =
pref.getBoolean(context
.getString(R.string.pref_activate_notification_key), true);
if(wantNotif)
{
BackgroundTasks.executeTask(context,
BackgroundTasks.ACTION_NOTIFY_USER_GEOFENCES_REGISTERED);
}
jobFinished(job, false);
}
};
mBackgroundTask.execute();
return true;
}
Solution found. It is amazing how a simple solution can look like impossible to find out sometimes. When building the API client, add the callbacks and CONNECT the client.
// Build up the LocationServices API client
googleApiClient= new GoogleApiClient.Builder(context)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks()
{
#Override
public void onConnected(#Nullable Bundle bundle)
{ // add your stuff, we are connected
}
#Override
public void onConnectionSuspended(int i) {
googleApiClient.connect();
}
})
.addApi(LocationServices.API)
.addApi(Places.GEO_DATA_API)
.build();
// CONNECT the client
if (!googleApiClient.isConnecting() || !googleApiClient.isConnected())
{
googleApiClient.connect();
}
I have this activity:
public class AMLoginActivity extends Activity implements IAsyncResponse {
public static int finished;
private final String TAG = "AMLoginActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finished = 0;
Intent i = new Intent(AMLoginActivity.this, GDLoginActivity.class);
i.putExtra("response", this);
AMLoginActivity.this.startActivity(i);
}
public void processFinish(){
finished++;
Log.i(TAG, "Number finished: " + finished);
if(finished == 1){
Log.i(TAG, "All finished");
AMLoginActivity.this.finish();
Log.i(TAG, "Finish called");
}
}
Which calls the GDLoginActivity to login to google drive. It can be seen below:
public class GDLoginActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "GDLoginActivity";
private static final int REQUEST_CODE_RESOLUTION = 3;
private static GoogleApiClient mGoogleApiClient;
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Log.i(TAG, "New GDClient created");
}
// Connect the client.
mGoogleApiClient.connect();
}
#Override
protected void onPause() {
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
super.onPause();
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
IAsyncResponse response = (IAsyncResponse) getIntent().getSerializableExtra("response");
Log.i(TAG, "Process finish");
response.processFinish();
finish();
}
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "GoogleApiClient connection suspended");
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Called whenever the API client fails to connect.
Log.i(TAG, "GoogleApiClient connection failed: " + result.toString());
if (!result.hasResolution()) {
// show the localized error dialog.
GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 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.
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
public static GoogleApiClient getGoogleApiClient(){
return mGoogleApiClient;
}
}
The issue is that when the GDLoginActivity connects and finish()'s, it should increment finish by 1 and and also finish the AMLoginActivity. It does increment by 1 and call finish() in processFinish(), but nothing happens and AMLoginActivity doesn't actually close (i.e. onDestroy() is never called), so i'm just left with a blank screen. If I remove GDLoginActivity and just call processFinish() instead, then AMLoginActivity finishes just fine, so I assume it has something to do with GDLoginActivity, but this is happening with other similar activities too. Any ideas?
Edit: Also if I hit the back button on the blank screen, then it calls the onDestroy() method of AMLoginActivity and goes to the activity I want, if that hints a clue at what is going on?
It looks like you're finishing them in a weird order. Try finishing the visible activity before you finish the one that started it.
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
IAsyncResponse response = (IAsyncResponse) getIntent().getSerializableExtra("response");
Log.i(TAG, "Process finish");
//finishes the previous activity
response.processFinish();
//finishes the visible activity
finish();
//try flipping this order ^
}
You could use startActivitForResult() if you're trying to finish one activity after another has finished.
I got a problem with the Google android wear Data Layer Api...
I already used it to call handheld activities from a wearable activity and it worked just fine. But now I want call a handheld activity from a watchface service...
I created a Google API Client and added wearableApi:
public void onCreate(SurfaceHolder holder) {
super.onCreate(holder);
setWatchFaceStyle(new WatchFaceStyle.Builder(MyWatchFace.this)
.setCardPeekMode(WatchFaceStyle.PEEK_MODE_VARIABLE)
.setBackgroundVisibility(WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE)
.setShowSystemUiTime(false)
.setAcceptsTapEvents(true)
.build());
mGoogleApiClient = new GoogleApiClient.Builder(MyWatchFace.this)
.addApi(Wearable.API)
.build();
mGoogleApiClient.connect();
Then I used these methods to send the data:
public void startActivity()
{
HashSet<String> results = new HashSet<String>();
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
#Override
public void onResult(NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
String handheld = getConnectedNodesResult.getNodes().get(0).getId();
Toast.makeText(MyWatchFace.this, getConnectedNodesResult.getNodes().get(0).getDisplayName()+": "+ handheld, Toast.LENGTH_SHORT).show();
sendStartActivityMessage(handheld, giveValueXYZ());
}
});
private void sendStartActivityMessage(String nodeId, String data) {
byte[] dataArray = data.getBytes();
Toast.makeText(MyWatchFace.this, "ActivityPath: "+ START_ACTIVITY_PATH, Toast.LENGTH_SHORT).show();
Wearable.MessageApi.sendMessage(
mGoogleApiClient, nodeId, START_ACTIVITY_PATH, dataArray).setResultCallback(
new ResultCallback<MessageApi.SendMessageResult>() {
#Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
if (!sendMessageResult.getStatus().isSuccess()) {
Log.e(TAG, "Failed to send message with status code: "
+ sendMessageResult.getStatus().getStatusCode());
}
}
});
}
On the mobile site I used this code to listen for the messages:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_host_main);
context = getApplicationContext();
...
//Google Api
final GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API).build();
googleApiClient.connect();
Wearable.MessageApi.addListener(googleApiClient, this);
...
public void onMessageReceived(MessageEvent messageEvent) {
if (messageEvent.getPath().equals(START_ACTIVITY_PATH_WEARDATA)) {
Log.d(TAG, "getPath: " + messageEvent.getPath() + "|||getData: " + messageEvent.getData());
someActions();
}
All this works perfectly fine if I send the message from a wearable activity but does not even trigger the onMessageReceived(...) methode if I send a message from the watchface service...
Could there be a problem with my package names?
mobile :com.example.janik.xxx.xxx
watchface: de.WatchSmart.watch_smart_watch_face_service
How does the client know which Data Layer Api message is adressed to him?
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();
}
}
});
}
}
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.