Use the Login with Amazon SDK for Android APIs (v2.0.2 and below)
Note that the instructions below apply only to older versions of the Login with Amazon SDK for Android (versions 2.0.2 and below).
Older SDKs are no longer available for download, but we have preserved the instructions here for the convenience of our developers who are still using them.
- Installing the Android Developer Tools
- Handle the Login Button and get Profile Data
- Check for User Login at Startup
- Clear Authorization State and Log Out a User
- Call AmazonAuthorizationManager Methods Synchronously
Installing the Android Developer Tools
The Login with Amazon SDK for Android will help you add Login with Amazon to your Android, Fire TV, and Fire tablet applications. We recommend you use the Login with Amazon SDK for Android with Android Studio, however, you can also use Eclipse with the ADT plugin. For steps on how to install Android Studio and on getting the Android SDK set up, see Get the Android SDK on developer.android.com
When the Android SDK is installed, find the SDK Manager application in your android installation. To develop for Login with Amazon, you must use the SDK Manager to install the SDK Platform for Android 2.2 or higher (API version 9). See Adding SDK Packages on developer.android.com for more information on using SDK Manager.
After installing the SDK, set up an Android Virtual Device (AVD) for running your apps. See Managing Virtual Devices on developer.android.com for instructions on setting up a virtual device.
Handle the Login Button and get Profile Data
This section explains how to call the authorize
and getProfile
APIs to login a user and retrieve their profile data. This includes creating an onClick
listener for your Login with Amazon button in the onCreate
method of your app.
Import the Login with Amazon API to your source file.
-
Import the Login with Amazon API to your source file.
To import the Login with Amazon API, add the following
import
statements to your source file:import com.amazon.identity.auth.device.AuthError; import com.amazon.identity.auth.device.authorization.api.AmazonAuthorizationManager; import com.amazon.identity.auth.device.authorization.api.AuthorizationListener; import com.amazon.identity.auth.device.authorization.api.AuthzConstants;
-
Initialize the
AmazonAuthorizationManager
. You will need to declare aAmazonAuthorizationManager
variable and create a new instance of the class. Creating a new instance only requires your current application context and an empty bundle. The best place to initialize theAmazonAuthorizationManager
is in theonCreate
method of yourActivity
. For example:private AmazonAuthorizationManager mAuthManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAuthManager = new AmazonAuthorizationManager(this, Bundle.EMPTY); }
-
Create an
AuthorizeListener
.AuthorizeListener
implements theAuthorizationListener
interface, and will process the result of theauthorize
call. It contains three methods,onSuccess
,onError
, andonCancel
. Each method receives either aBundle
or anAuthError
object.private class AuthorizeListener implements AuthorizationListener{ /* Authorization was completed successfully. */ @Override public void onSuccess(Bundle response) { } /* There was an error during the attempt to authorize the application. */ @Override public void onError(AuthError ae) { } /* Authorization was cancelled before it could be completed. */ @Override public void onCancel(Bundle cause) { } }
-
Call
AmazonAuthorizationManager.authorize
.In the
onClick
handler for your Login with Amazon button, callauthorize
to prompt the user to login and authorize your application.This method is responsible for authorizing the customer in one of the following ways:
-
Switches to the system browser and lets the customer sign in and consent to the requested information.
-
Switches to web view in a secure context, to let the customer sign in and consent to the requested information.
This secure context for #2 is currently made available as the Amazon Shopping app on Android devices. Amazon-created devices running Fire OS (for example Fire Tablets, and Fire TVs) always use this option even if there is no Amazon Shopping app on the device. Because of this, if the customer is already signed in to the Amazon Shopping app, this API will skip the sign-in page, leading to a Single Sign On experience for the customer.
When your application is authorized, it is authorized for one or more data sets known as scopes. The first parameter is an array of scopes that encompass the user data that you are requesting from Login with Amazon. The first time a user logs in to your app, they will be presented with a list of the data you are requesting and asked for approval. Login with Amazon currently supports three scopes:
profile
, which contains the user's name, email address, and Amazon account id;profile:user_id
, which contains only the Amazon account id; andpostal_code
, which contains the user's zip/postal code.The best way to call
authorize
is asynchronously, so you do not have to block the UI thread or create a worker thread of your own. To callauthorize
asynchronously, pass an object that supports theAuthorizationListener
interface as the last parameter:private AmazonAuthorizationManager mAuthManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAuthManager = new AmazonAuthorizationManager(this, Bundle.EMPTY); // Find the button with the login_with_amazon ID // and set up a click handler mLoginButton = (Button) findViewById(R.id.login_with_amazon); mLoginButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mAuthManager.authorize( new String []{"profile","postal_code"}, Bundle.EMPTY, new AuthorizeListener()); } }); }
-
-
Create a
ProfileListener
.ProfileListener
is our name for a class that implements theAPIListener
interface, and will process the result of thegetProfile
call.APIListener
contains two methods,onSuccess
andonError
(it does not support onCancel because there is no way to cancel a getProfile call).onSuccess
receives aBundle
object with profile data, whileonError
receives anAuthError
object with information on the error.private class ProfileListener implements APIListener{ /* getProfile completed successfully. */ @Override public void onSuccess(Bundle response) { } /* There was an error during the attempt to get the profile. */ @Override public void onError(AuthError ae) { } }
-
Implement
onSuccess
for yourAuthorizeListener
. InonSuccess
, callAmazonAuthorizationManager.getProfile
to retrieve the customer profile .getProfile
, likeauthorize
, uses an asynchronous listener interface. ForgetProfile
, that interface isAPIListener
, notAuthorizationListener
./* Authorization was completed successfully. */ @Override public void onSuccess(Bundle response) { mAuthManager.getProfile(new ProfileListener()); }
-
Implement
onSuccess
for yourProfileListener
.onSuccess
has two main tasks; retrieve the profile data from the responseBundle
, and pass the data to the UI.updateProfileData
is a hypothetical function your app could implement to display profile details.setLoggedInState
, another hypothetical function, would indicate that a user is logged in and give them a means of logging out. To retrieve the profile data from theBundle
, we use names stored by theAuthzConstants
class. TheonSuccess
bundle contains the profile data in aBUNDLE_KEY.PROFILE
bundle. Within the profile bundle, the scope data is indexed underPROFILE_KEY.NAME
,PROFILE_KEY.EMAIL
,PROFILE_KEY.USER_ID
, andPROFILE_KEY.POSTAL_CODE
.PROFILE_KEY.POSTAL_CODE
is only included if you request thepostal_code
scope.@Override public void onSuccess(Bundle response) { // Retrieve the data we need from the Bundle Bundle profileBundle = response.getBundle( AuthzConstants.BUNDLE_KEY.PROFILE.val); String name = profileBundle.getString( AuthzConstants.PROFILE_KEY.NAME.val); String email = profileBundle.getString( AuthzConstants.PROFILE_KEY.EMAIL.val); String account = profileBundle.getString( AuthzConstants.PROFILE_KEY.USER_ID.val); String zipcode = profileBundle.getString( AuthzConstants.PROFILE_KEY.POSTAL_CODE.val); runOnUiThread(new Runnable() { @Override public void run() { updateProfileData(name, email, account, zipcode); } }); }
-
Implement
onError
for yourProfileListener
.onError
includes anAuthError
object containing details about the error./* There was an error during the attempt to get the profile. */ @Override public void onError(AuthError ae) { /* Retry or inform the user of the error */ }
-
Implement
onError
for yourAuthorizeListener
./* There was an error during the attempt to authorize the application. */ @Override public void onError(AuthError ae) { /* Inform the user of the error */ }
-
Implement
onCancel
for yourAuthorizeListener
. Because the authorization process presents a login screen (and possibly a consent screen ) to the user in a web browser (or a webview), the user will have an opportunity to cancel the login or navigate away from the web page. If they explicitly cancel the login process,onCancel
is called. IfonCancel
is called, you will want to reset your UI./* Authorization was cancelled before it could be completed. */ @Override public void onCancel(Bundle cause) { /* reset the UI to a ready-to-login state */ }
Note: If the user navigates away from the login screen in the browser or webview and switches back to your app, the SDK will not detect that the login was not completed. If you detect user activity in your app before login is completed, you can assume they have navigated away from the browser and react accordingly.
Check for User Login at Startup
If a user logs into your app, closes the app, and restarts the app later, the app is still authorized to retrieve data. The user is not logged out automatically. At startup, you can show the user as logged in if your app is still authorized. This section explains how to use getToken
to see if the app is still authorized.
-
Create a
TokenListener
.TokenListener
implements theAPIListener
interface, and will process the result of thegetToken
call.APIListener
contains two methods,onSuccess
andonError
(it does not support onCancel because there is no way to cancel agetToken
call).onSuccess
receives aBundle
object with token data, whileonError
receives anAuthError
object with information on the error.private class TokenListener implements APIListener{ /* getToken completed successfully. */ @Override public void onSuccess(Bundle response) { } /* There was an error during the attempt to get the token. */ @Override public void onError(AuthError ae) { } }
-
In the
onStart
method of yourActivity
, callgetToken
to see if the application is still authorized.getToken
retrieves the raw access token that theAmazonAuthorizationManager
uses to access a customer profile. If the token value is notnull
, then the app is still authorized and a call togetProfile
should succeed.getToken
requires the same scopes you requested in your call toauthorize
.getToken
supports asychronous calls in the same manner asgetProfile
, so you do not have to block the UI thread or create a worker thread of your own. To callgetToken
asynchronously, pass an object that supports theAPIListener
interface as the final parameter.@Override protected void onStart(){ super.onStart(); mAuthManager.getToken(new String []{"profile","postal_code"}, new TokenListener()); }
-
Implement
onSuccess
for yourTokenListener
.onSuccess
has two tasks: to retrieve the token from theBundle
, and if the token is valid, to callgetProfile
. To retrieve the token data from theBundle
, we use names stored by theAuthzConstants
class. TheonSuccess
bundle contains the token data in aBUNDLE_KEY.TOKEN
value. If that value is not null, this example callsgetProfile
using the same listener you declared in the previous section (see steps 7 and 8)./* getToken completed successfully. */ @Override public void onSuccess(Bundle response) { final String authzToken = response.getString(AuthzConstants.BUNDLE_KEY.TOKEN.val); if (!TextUtils.isEmpty(authzToken)) { // Retrieve the profile data mAuthManager.getProfile(new ProfileListener()); } }
Clear Authorization State and Log Out a User
The clearAuthorizationState
method will clear the user's authorization data from the AmazonAuthorizationManager
local data store. A user will have to log in again in order for the app to retrieve profile data. Use this method to log out a user, or to troubleshoot login problems in the app.
- Implement a logout mechanism. After a user has successfully logged in, you should provide a logout mechanism so they can clear their profile data and previously authorized scopes. Your mechanism might be a hyperlink, or a menu item. For this example we will create an
onClick
method for a button. - In your logout handler, call
clearAuthorizationState
.clearAuthorizationState
will remove a user's authorization data (access tokens, profile) from the local store.clearAuthorizationState
takes no parameters except for anAPIListener
to return success or failure. - Declare an anonymous
APIListener
. Anonymous classes are a useful alternative to declaring a new class to implementAPIListener
. - Implement
onSuccess
inside theAPIListener
. WhenclearAuthorizationState
succeeds you should update your UI to remove references to the user, and provide a login mechanism users can use to log in again. - Implement
onError
inside theAPIListener
. IfclearAuthorizationState
returns an error, you can let the user try to logout again.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Previous onCreate declarations omitted */
// Find the button with the logout ID and set up a click handler
mLogoutButton = (Button) findViewById(R.id.logout);
mLogoutButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mAuthManager.clearAuthorizationState(new APIListener() {
@Override
public void onSuccess(Bundle results) {
// Set logged out state in UI
}
@Override
public void onError(AuthError authError) {
// Log the error
}
});
}
});
}
Call AmazonAuthorizationManager Methods Synchronously
Some AmazonAuthorizationManager
methods return a Future
object. This allows you to call the method synchronously instead of passing a listener as a parameter. If you do use a Future
, you should not use it on a UI thread. If you block a UI thread for more than five seconds you will get an ANR (Application Not Responding) prompt. In the Handling the Login Button and Getting Profile Data example above, the onSuccess
method for AuthorizeListener
is called with a worker thread created by AmazonAuthorizationManager
. This means it is safe to use that thread to call getProfile
synchronously. To make a synchronous call, assign the return value from getProfile
to a Future
object, and call the get
method on that object to wait until the method completes.
Future.get
returns a Bundle
object that contains a FUTURE_TYPE
value of SUCCESS
, ERROR
, or CANCEL
. If the method was a success, the same bundle will contain PROFILE_KEY
values for the profile data. For example:
/* Authorization was completed successfully. */
@Override
public void onSuccess(Bundle response) {
Future<Bundle> future = mAuthManager.getProfile(null);
Bundle result = future.get();
// Find out if the call succeeded, and retrieve the profile
Object future_type = result.get(AuthzConstants.BUNDLE_KEY.FUTURE.val);
if (future_type == AuthzConstants.FUTURE_TYPE.SUCCESS)
{
String name = result.getString(
AuthzConstants.PROFILE_KEY.NAME.val);
String email = result.getString(
AuthzConstants.PROFILE_KEY.EMAIL.val);
String account = result.getString(
AuthzConstants.PROFILE_KEY.USER_ID.val);
String zipcode = result.getString(
AuthzConstants.PROFILE_KEY.POSTAL_CODE.val);
runOnUiThread(new Runnable() {
@Override
public void run() {
updateProfileData(name, email, account, zipcode);
}
});
}
else if (future_type == AuthzConstants.FUTURE_TYPE.ERROR)
{
// Get error object
AuthError authError = AuthError.extractError(result);
/* Use authError to diagnose error */
}
else if (future_type == AuthzConstants.FUTURE_TYPE.CANCEL)
{
/* User cancelled during authorization */
}
}
Last updated: Dec 01, 2022