package de.sebse.fuplanner.services.GoogleAuth; import android.content.Intent; import android.content.IntentSender; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.FragmentActivity; import android.util.Log; import android.widget.Toast; import com.google.android.gms.auth.api.Auth; import com.google.android.gms.auth.api.credentials.Credential; import com.google.android.gms.auth.api.credentials.CredentialRequest; import com.google.android.gms.auth.api.credentials.CredentialRequestResponse; import com.google.android.gms.auth.api.credentials.CredentialRequestResult; import com.google.android.gms.auth.api.credentials.CredentialsClient; import com.google.android.gms.auth.api.credentials.CredentialsOptions; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.CommonStatusCodes; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.ResolvableApiException; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import static android.app.Activity.RESULT_OK; /** * Created by ***REMOVED*** on 06.11.2017. */ public class GoogleAuth { // https://developers.google.com/identity/smartlock-passwords/android/retrieve-credentials private static final String TAG = "GoogleAuth"; private final FragmentActivity activity; private CredentialsClient mCredentialsClient; private boolean mIsResolving; public GoogleAuth(FragmentActivity activity) { this.activity = activity; } public void connect(final ConnectedListener listener) { if (!this.isAvailable()) { Log.d(TAG, "STATUS: Google auth not available!"); listener.connected(); return; } this.mCredentialsClient = getClient(new GoogleApiClient.ConnectionCallbacks() { @Override public void onConnected(@Nullable Bundle bundle) { listener.connected(); } @Override public void onConnectionSuspended(int i) { } }, new GoogleApiClient.OnConnectionFailedListener() { @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } }); } public void getLoginState(final CredentialsListener credentialsListener) { if (!this.isAvailable()) { Log.d(TAG, "STATUS: Google auth not available!"); credentialsListener.onCredentials(null); return; } CredentialRequest request = new CredentialRequest.Builder() .setPasswordLoginSupported(true) .build(); mCredentialsClient.request(request).addOnCompleteListener( new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { // Successfully read the credential without any user interaction, this // means there was only a single credential and the user has auto // sign-in enabled. Credential credential = task.getResult().getCredential(); credentialsListener.onCredentials(new Credentials(credential.getId(), credential.getPassword())); return; } Exception e = task.getException(); if (e instanceof ResolvableApiException) { // This is most likely the case where the user has multiple saved // credentials and needs to pick one. This requires showing UI to // resolve the read request. ResolvableApiException rae = (ResolvableApiException) e; resolveResult(rae, RequestCode.RC_READ); return; } if (e instanceof ApiException) { ApiException ae = (ApiException) e; if (ae.getStatusCode() == CommonStatusCodes.SIGN_IN_REQUIRED) { // This means only a hint is available, but we are handling that // elsewhere so no need to act here. } else { Log.w(TAG, "Unexpected status code: " + ae.getStatusCode()); } } } }); /*Auth.CredentialsApi.request(this.mCredentialsClient, mCredentialRequest).setResultCallback( new ResultCallback() { @Override public void onResult(@NonNull CredentialRequestResult credentialRequestResult) { if (credentialRequestResult.getStatus().isSuccess()) { // See "Handle successful credential requests" Credential credential = credentialRequestResult.getCredential(); credentialsListener.onCredentials(new Credentials(credential.getId(), credential.getPassword())); } else { // See "Handle unsuccessful and incomplete credential requests" credentialsListener.onCredentials(null); } } } );*/ } public void setLoginState(String username, String password) { if (!this.isAvailable()) { Log.d(TAG, "STATUS: Google auth not available!"); Toast.makeText(activity, "Google auth not available!", Toast.LENGTH_SHORT).show(); return; } Credential credential = new Credential.Builder(username) .setPassword(password) .build(); mCredentialsClient.save(credential).addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { showToast("Credential saved."); return; } Exception e = task.getException(); if (e instanceof ResolvableApiException) { // The first time a credential is saved, the user is shown UI // to confirm the action. This requires resolution. ResolvableApiException rae = (ResolvableApiException) e; resolveResult(rae, RequestCode.RC_SAVE); } else { // Save failure cannot be resolved. Log.w(TAG, "Save failed.", e); showToast("Credential Save Failed"); } } }); /*Auth.CredentialsApi.save(mCredentialsClient, credential).setResultCallback( new ResultCallback() { @Override public void onResult(@NonNull Status status) { if (status.isSuccess()) { Log.d(TAG, "SAVE: OK"); Toast.makeText(activity, "Credentials saved", Toast.LENGTH_SHORT).show(); } else { Log.d(TAG, String.valueOf(status.hasResolution())); Log.d(TAG, String.valueOf(status.getStatus())); if (status.hasResolution()) { // Try to resolve the save request. This will prompt the user if // the credential is new. try { status.startResolutionForResult(activity, RC_SAVE); } catch (IntentSender.SendIntentException e) { // Could not resolve the request Log.e(TAG, "STATUS: Failed to send resolution.", e); Toast.makeText(activity, "Save failed", Toast.LENGTH_SHORT).show(); } } else { // Request has no resolution Toast.makeText(activity, "Save failed", Toast.LENGTH_SHORT).show(); } } } } );*/ } public void deleteLoginState(String username, String password) { if (!this.isAvailable()) { Log.d(TAG, "STATUS: Google auth not available!"); return; } Credential credential = new Credential.Builder(username) .setPassword(password) .build(); Auth.CredentialsApi.delete(mCredentialsClient, credential).setResultCallback( new ResultCallback() { @Override public void onResult(Status status) { if (status.isSuccess()) { // Credential was deleted successfully } } } ); } private boolean isAvailable() { return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this.activity) == ConnectionResult.SUCCESS; } private CredentialsClient getClient(@NonNull GoogleApiClient.ConnectionCallbacks connectionCallbacks, @NonNull GoogleApiClient.OnConnectionFailedListener failedListener) { CredentialsOptions options = new CredentialsOptions.Builder() .forceEnableSaveDialog() .build(); return com.google.android.gms.auth.api.credentials.Credentials.getClient(this.activity, options); /*return new GoogleApiClient.Builder(this.activity) .addConnectionCallbacks(connectionCallbacks) .enableAutoManage(this.activity, failedListener) .addApi(Auth.CREDENTIALS_API) .build();*/ } public void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d(TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data); switch (requestCode) { case RequestCode.RC_HINT: // Drop into handling for RC_READ case RequestCode.RC_READ: if (resultCode == RESULT_OK) { boolean isHint = (requestCode == RequestCode.RC_HINT); Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY); processRetrievedCredential(credential, isHint); } else { Log.e(TAG, "Credential Read: NOT OK"); showToast("Credential Read Failed"); } mIsResolving = false; break; case RequestCode.RC_SAVE: if (resultCode == RESULT_OK) { Log.d(TAG, "Credential Save: OK"); showToast("Credential Save Success"); } else { Log.e(TAG, "Credential Save: NOT OK"); showToast("Credential Save Failed"); } mIsResolving = false; break; } } private void resolveResult(ResolvableApiException rae, int requestCode) { // We don't want to fire multiple resolutions at once since that can result // in stacked dialogs after rotation or another similar event. if (mIsResolving) { Log.w(TAG, "resolveResult: already resolving."); return; } Log.d(TAG, "Resolving: " + rae); try { rae.startResolutionForResult(this.activity, requestCode); mIsResolving = true; } catch (IntentSender.SendIntentException e) { Log.e(TAG, "STATUS: Failed to send resolution.", e); } } /** Display a short Toast message **/ private void showToast(String msg) { Toast.makeText(this.activity, msg, Toast.LENGTH_SHORT).show(); } }