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();
}
}