Cover image: “Museu Berardo”

I hope you learned a bit about using Smart Lock for Passwords, by reading the first part of this series. Without further ado, let’s take a look at how easy it is to implement.

You’ll need to have Play Services as a dependency for your app:

dependencies {
  compile 'com.google.android.gms:play-services-auth:8.3.0'
}

Next, add a GoogleApiClient to your activity. This is the usual Play Services implementation, which you probably have already dealt with. I’ll leave the nitty gritty to you, but you can find a step-by-step guide on the Google Developers website.


Retrieve credentials

Once that’s done, it’s really easy to request any stored credentials, using this snippet:

CredentialRequest credentialsRequest = 
  new CredentialRequest.Builder()
    .setSupportsPasswordLogin(true)
    .build();

Auth.CredentialsApi
  .request(apiClient, credentialsRequest)
  .setResultCallback(myCallback);

The callback is a ResultCallback<CredentialRequestResult>, where the (successful) result you receive in onResult() contains the credentials that you can then use to populate the UI.


Store new credentials

To store new credentials, simply pass an object containing the credentials to save:

Auth.CredentialsApi
  .save(credentialsClient, credentials)
  .setResultCallback(myCallback);

The Credential class is a simple key-value pair holder, for us, that contains the username and password we want to store. Also of note, you can keep more than one set of saved credentials per app at any given time in Smart Lock.

If that was the case, when you try to load them, you’ll be presented with an error with a resolution. Launching that resolution will prompt the user to pick which of the stored credentials to use. The normal flow will then resume.


Delete stored credentials

To delete a set of saved credentials, use the delete method:

Auth.CredentialsApi
  .delete(credentialsClient, credentials)
  .setResultCallback(myCallback);

The credentials object doesn’t have to be the same instance you get back from Smart Lock. You can create a new one using the same data and it will still work. You don’t need to keep the credentials object around.


Hint email from the device’s accounts

Lastly, even if a user has no saved account info, you may want to use their email to help them sign up quickly.

PendingIntent pendingIntent = Auth.CredentialsApi
  .getHintPickerIntent(credentialsClient, hintRequest);

startIntentSenderForResult(
  pendingIntent.getIntentSender(),
  MY_REQUEST_CODE_SIGNIN_HINT,
  null, 
  0,
  0,
  0
);

This will display a dialog that allows the user to use one of their device accounts email addresses, or enter a new one. Smart Lock will remember email addresses the user has used previously and propose them again.

The hintRequest allows some customisation of the dialog. It is constructed simply using the HintRequest.Builder.

If the user has picked one of their Google accounts, you will get the following information in the result callback:

- a Credential object that contains the user ID (the email) - one or more authentication tokens (OpenID tokens — not used in our example) - optionally, the display name and avatar image URL for the user.

This should also contain a generated password, but in my tests it has always been null.


Bringing it all together

Please review the source code for this article on GitHub, if you would like a more complete sample implementation:

https://github.com/rock3r/smartlock-demo

The code in that repo is based on the official sample code for Smart Lock, but is more complete and shows how to handle more possible edge cases.

Now go out there and make your users’ lives easier!

Thanks to Mike Wolfson and Said Tahsin Dane for proofreading, and everyone from Google I chatted with about this.