mpao
9/14/2016 - 9:49 AM

Smart Lock for Passwords on Android

Smart Lock for Passwords on Android

package io.github.mpao.googlesmartlock;

import android.content.Intent;
import android.content.IntentSender;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
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.CredentialRequestResult;
import com.google.android.gms.auth.api.credentials.IdentityProviders;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;

public class MainActivity extends AppCompatActivity implements
        GoogleApiClient.OnConnectionFailedListener,
        GoogleApiClient.ConnectionCallbacks {

    private static final String TAG     = "SAMPLES";
    private static final int RC_SIGN_IN = 1;
    private static final int RC_READ    = 2;
    private static final int RC_SAVE    = 3;

    private GoogleApiClient googleApiClient;
    private CredentialRequest credentialRequest;
    private Credential credential;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /*
        To request stored credentials, you must create an instance of GoogleApiClient
        configured to access the Credentials API.
         */
        GoogleSignInOptions.Builder gsoBuilder = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).requestEmail();
        googleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .enableAutoManage(this, this)
                .addApi(Auth.CREDENTIALS_API)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gsoBuilder.build())
                .build();
        /*
        A CredentialRequest object specifies the sign-in systems from which you want to request credentials.
        Build a CredentialRequest using the setPasswordLoginSupported method for password-based sign-in,
        and the setAccountTypes() method for federated sign-in services such as Google Sign-In.
        Use the constants defined in IdentityProviders to specify commonly-used sign-in providers.
        For other sign-in providers, use any string that uniquely identifies the provider.
        You must use the same provider identifier to store credentials as you use to retrieve the credentials.
         */

        credentialRequest = new CredentialRequest.Builder()
                .setPasswordLoginSupported(false)
                .setAccountTypes(IdentityProviders.GOOGLE)
                .build();


        Button button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onGoogleSignInClicked();
            }
        });

        Button button2 = (Button)findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Auth.CredentialsApi.delete(googleApiClient, credential).setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(@NonNull Status status) {
                        if (status.isSuccess()) {
                            // Credential was deleted successfully
                            Log.e(TAG, "cancellato");
                        }
                    }
                });

            }
        });

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == RC_SIGN_IN) {
            if (resultCode == RESULT_OK) {
                credential = data.getParcelableExtra(Credential.EXTRA_KEY);
                onCredentialRetrieved(credential);
            } else {
                Log.e(TAG, "Credential Read: NOT OK");
                Toast.makeText(this, "Login con mail necessaria", Toast.LENGTH_SHORT).show();
            }
        }

        if (requestCode == RC_READ) {
            if (resultCode == RESULT_OK) {
                credential = data.getParcelableExtra(Credential.EXTRA_KEY);
                onCredentialRetrieved(credential);
            } else {
                Log.e(TAG, "Credential Read: NOT OK");
                Toast.makeText(this, "Login con mail necessaria", Toast.LENGTH_SHORT).show();
            }
        }



        if (requestCode == RC_SAVE) {
            if (resultCode == RESULT_OK) {
                Log.d(TAG, "SAVE: OK");
                Toast.makeText(this, "Credentials saved", Toast.LENGTH_SHORT).show();
            } else {
                Log.i(TAG, "SAVE: Canceled by user");
            }
        }

    }

    private void onGoogleSignInClicked() {

        Auth.CredentialsApi.request(googleApiClient, credentialRequest).setResultCallback(
                new ResultCallback<CredentialRequestResult>() {
                    @Override
                    public void onResult(@NonNull CredentialRequestResult credentialRequestResult) {
                        if (credentialRequestResult.getStatus().isSuccess()) {
                            // See "Handle successful credential requests"
                            credential = credentialRequestResult.getCredential();
                            onCredentialRetrieved(credential);
                        } else {
                            // See "Handle unsuccessful and incomplete credential requests"
                            notLoggedYet(credentialRequestResult.getStatus());
                        }
                    }
                });

    }

    private void notLoggedYet( Status status){

        if ( status.getStatusCode() == CommonStatusCodes.RESOLUTION_REQUIRED ) {
            // più di un account tra cui scegliere per il login, oppure utente non loggato
            try {
                status.startResolutionForResult(this, RC_READ);
            } catch (IntentSender.SendIntentException e) {
                Log.e(TAG, "STATUS: Failed to send resolution.", e);
            }
        }else if( status.getStatusCode() == CommonStatusCodes.SIGN_IN_REQUIRED ) {

            try {
                status.startResolutionForResult(this, RC_SIGN_IN);
            } catch (IntentSender.SendIntentException e) {
                Log.e(TAG, "STATUS: Failed to send resolution.", e);
            }

        }else{
            // The user must create an account or sign in manually.
            Log.e(TAG, "STATUS: Unsuccessful credential request.");
        }

    }

    private void onCredentialRetrieved(Credential credential) {

        Log.e(TAG, credential.getId());
        Log.e(TAG, credential.getName());
        Log.e(TAG, credential.getAccountType());

        String avatar = credential.getProfilePictureUri()==null ? "" : credential.getProfilePictureUri().toString();
        Log.e(TAG, avatar );

        String idToken = credential.getIdTokens().isEmpty() ? "nd" : credential.getIdTokens().get(0).getIdToken();
        Log.e(TAG, idToken );

        saveCredential(credential);

    }

    private void saveCredential(Credential credential){

        Auth.CredentialsApi.save(googleApiClient, credential).setResultCallback(new ResultCallback<Status>() {
            @Override
            public void onResult(@NonNull Status status) {
                if (status.isSuccess()) {
                    Log.d(TAG, "SAVE: OK");
                    Toast.makeText(MainActivity.this, "Credentials saved", Toast.LENGTH_SHORT).show();
                }
            }
        });


    }

    /*
        METODI INTERFACCE
     */
    @Override
    public void onConnected(Bundle bundle) {
        // salva credenziali
    }

    @Override
    public void onConnectionSuspended(int i) {}

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.w(TAG, "onConnectionFailed:" + connectionResult);
        Toast.makeText(this, "An error has occurred.", Toast.LENGTH_SHORT).show();
    }
}