/*
* Copyright (c) 2016 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.samples.apps.iosched.login;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.Toast;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Scope;
import com.google.android.gms.common.api.Status;
import com.google.samples.apps.iosched.R;
import com.google.samples.apps.iosched.util.AccountUtils;
import static com.google.samples.apps.iosched.util.LogUtils.LOGD;
import static com.google.samples.apps.iosched.util.LogUtils.LOGI;
/**
* Wrapper activity responsible for handling user switching using the GoogleApiClient.
*
* <p>Rendered as a transparent activity, this class is responsible for launching the user account
* switcher, and receiving the results once the user has made a selection.
*
* <p>Note that invoking this will immediately sign the current user out. In the event the account
* picker is canceled by the user, we attempt to restore the old user.
*/
public class SwitchUserActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final int RC_SIGN_IN = 1;
private static final String TAG = "SwitchUserActivity";
private GoogleApiClient mGoogleApiClient;
private String mPreviousUser;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Configure Google API client for use with login API
GoogleSignInOptions.Builder gsoBuilder =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN);
for (String scope : LoginAndAuthWithGoogleApi.GetAuthScopes()) {
gsoBuilder.requestScopes(new Scope(scope));
}
GoogleSignInOptions gso = gsoBuilder.requestEmail().build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient != null) {
mGoogleApiClient.disconnect();
}
}
@Override
public void onConnected(@Nullable final Bundle bundle) {
mPreviousUser = AccountUtils.getActiveAccountName(this);
LOGD(TAG, "Signing current user out (" + mPreviousUser + ")");
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(new SignOutCallback());
}
@Override
public void onConnectionSuspended(final int i) {
Toast.makeText(this, getText(R.string.google_play_services_disconnected),
Toast.LENGTH_SHORT).show();
// In this case we terminate, since otherwise we don't have any visible UI in this scenario.
finish();
}
@Override
public void onConnectionFailed(@NonNull final ConnectionResult connectionResult) {
Toast.makeText(this, getText(R.string.google_play_services_disconnected),
Toast.LENGTH_SHORT).show();
finish();
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode,
final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
/**
* Update active account and inform calling task of result completion.
* Invoked after after the GoogleSignInApi login process completes (which is itself invoked
* in SignOutCallback).
*
* <p>In the event the user cancels login, the last known user is restored.
*
* @param result User data from GoogleSignInApi
*/
private void handleSignInResult(final GoogleSignInResult result) {
if (result.isSuccess()) {
final GoogleSignInAccount newUser = result.getSignInAccount();
if (newUser != null) {
AccountUtils.setActiveAccount(this, newUser.getEmail());
LOGI(TAG, "Switched to user: " + newUser);
setResult(Activity.RESULT_OK);
}
} else {
// Login failed, revert to previous user to simulate spinner behavior
LOGI(TAG, "Account switch aborted, re-enabling previous user: " + mPreviousUser);
AccountUtils.setActiveAccount(this, mPreviousUser);
setResult(Activity.RESULT_CANCELED);
}
finish();
}
/**
* Invoked after the user has been signed out. Once this is done, we can safely start a new
* sign-in process.
*/
private class SignOutCallback implements ResultCallback<Status> {
@Override
public void onResult(@NonNull final Status status) {
AccountUtils.clearActiveAccount(SwitchUserActivity.this);
LOGD(TAG, "Launching account switcher");
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
SwitchUserActivity.this.startActivityForResult(signInIntent, RC_SIGN_IN);
}
}
}