Android用のLogin with Amazon SDK APIを使用する(v2.0.2以下)
以下の手順は、Android用のLogin with Amazon SDK(バージョン2.0.2以下)のみに適用されます。
古いSDKは既にダウンロードできなくなっていますが、使用を継続している開発者向けに手順を保存しています。
- Android Developer Toolsのインストール
- ログインボタンの処理とプロファイルデータの取得
- 起動時のユーザーログインの確認
- 認可状態の消去とユーザーのログアウト
- AmazonAuthorizationManagerメソッドの同期的な呼び出し
Android Developer Toolsのインストール
Android用のLogin with Amazon SDKを使用して、Android、Fire TV、FireタブレットのアプリにLogin with Amazonを追加できます。Android用のLogin with Amazon SDKと併せてAndroid Studioを使用することをお勧めしますが、EclipseとADTプラグインも使用できます。Android StudioのインストールとAndroid SDKのセットアップの手順については、developer.android.comのAndroid SDKのダウンロードページを参照してください。
Android SDKをインストールしたら、お使いのAndroidにSDK Managerアプリがあることを確認します。Login with Amazon向けの開発では、SDK Managerを使用して、Android 2.2以上(APIバージョン9)用のSDKプラットフォームをインストールする必要があります。SDK Managerの使用方法の詳細については、developer.android.comのIDEおよびSDK Toolsの更新を参照してください。
SDKをインストールしたら、アプリを実行するためのAndroid仮想デバイス(AVD)を設定します。仮想デバイスの設定手順については、developer.android.comの仮想端末の作成と管理を参照してください。
ログインボタンの処理とプロファイルデータの取得
このセクションでは、authorize
APIとgetProfile
APIを呼び出してユーザーをログインし、そのユーザーのプロファイルデータを取得する方法について説明します。これには、[Login with Amazon] ボタン用にonClick
リスナーをアプリのonCreate
メソッドに作成することが含まれます。
ソースファイルにLogin with Amazon APIをインポートする方法
-
ソースファイルにLogin with Amazon APIをインポートします。
Login with Amazon APIをインポートするには、ソースファイルに次の
import
ステートメントを追加します。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;
-
AmazonAuthorizationManager
を初期化します。AmazonAuthorizationManager
変数を宣言して、このクラスの新しいインスタンスを作成する必要があります。新しいインスタンスの作成に必要なのは、既存のアプリのコンテキストと空のバンドルのみです。AmazonAuthorizationManager
を初期化する場所として最も適しているのは、Activity
のonCreate
メソッド内です。次に例を示します。private AmazonAuthorizationManager mAuthManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAuthManager = new AmazonAuthorizationManager(this, Bundle.EMPTY); }
-
AuthorizeListener
を作成します。AuthorizeListener
はAuthorizationListener
インターフェイスを実装し、authorize
呼び出しの結果を処理します。これには、onSuccess
、onError
、onCancel
の3つのメソッドが含まれます。各メソッドはBundle
オブジェクトまたはAuthError
オブジェクトを受け取ります。private class AuthorizeListener implements AuthorizationListener{ /* 認可が正常に完了。 */ @Override public void onSuccess(Bundle response) { } /* アプリの認可中にエラーが発生。 */ @Override public void onError(AuthError ae) { } /* 完了前に認可がキャンセル。 */ @Override public void onCancel(Bundle cause) { } }
-
AmazonAuthorizationManager.authorize
を呼び出します。[Login with Amazon] ボタンの
onClick
ハンドラーで、authorize
を呼び出してユーザーにログインとアプリの認可を求める画面を表示します。このメソッドは、次のいずれかの方法でユーザーを認可するために使用されます。
-
システムブラウザに切り替えて、ユーザーがログインしてリクエストされた情報に同意できるようにする。
-
安全なコンテキストでWebViewに切り替えて、ユーザーがログインしてリクエストされた情報に同意できるようにする。
2番目の方法の安全なコンテキストは、現状ではAndroidデバイス上のAmazonショッピングアプリで使用できます。Fire OSが実行されているAmazon製のデバイス(Kindle Fire、Fire Phone、Fire TVなど)では、デバイスにAmazonショッピングアプリがインストールされていなくても常にこの方法が適用されます。このため、ユーザーがAmazonショッピングアプリにサインインしている場合は、APIによってサインインのページはスキップされ、ユーザーはシングルサインオンを実行できます。
アプリの認可時には、スコープと呼ばれるデータセット(1つ以上)に対して認可されます。最初のパラメーターは、Login with Amazonに対してリクエストしているユーザーデータを含むスコープの配列です。ユーザーが初めてアプリにログインするときに、開発者がリクエストして承認を求めているデータの一覧と一緒に提示されます。Login with Amazonで現在サポートしているスコープは次の3つです。
profile
には、ユーザー名、Eメールアドレス、AmazonアカウントIDが含まれます。profile:user_id
には、AmazonアカウントIDのみが含まれます。postal_code
には、ユーザーの郵便番号が含まれます。authorize
を呼び出す最も適切な方法は非同期呼び出しです。この場合、UIスレッドをブロックしたり、独自のワーカースレッドを作成したりする必要がありません。authorize
を非同期的に呼び出すには、AuthorizationListener
インターフェイスをサポートするオブジェクトを最後のパラメーターとして渡します。private AmazonAuthorizationManager mAuthManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAuthManager = new AmazonAuthorizationManager(this, Bundle.EMPTY); // login_with_amazon IDのボタンを検索し // クリックハンドラーをセットアップ 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()); } }); }
-
-
ProfileListener
を作成します。ProfileListener
はAPIListener
インターフェイスを実装するクラスの名前で、getProfile
呼び出しの結果を処理します。APIListener
にはonSuccess
とonError
の2つのメソッドが含まれます(getProfileの呼び出しをキャンセルする手段がないため、onCancelはサポートされていません)。onSuccess
はプロファイルデータを含むBundle
オブジェクトを受け取ります。onError
はエラーの情報を含むAuthError
オブジェクトを受け取ります。private class ProfileListener implements APIListener{ /* getProfileが正常に完了。 */ @Override public void onSuccess(Bundle response) { } /* プロファイルの取得中にエラーが発生。 */ @Override public void onError(AuthError ae) { } }
-
onSuccess
をAuthorizeListener
に実装します。onSuccess
で、AmazonAuthorizationManager.getProfile
を呼び出してユーザープロファイルを受け取ります。getProfile
は、authorize
と同じように、非同期リスナーインターフェイスを使用します。getProfile
では、そのインターフェイスがAuthorizationListener
ではなくAPIListener
になります。/* 認可が正常に完了。 */ @Override public void onSuccess(Bundle response) { mAuthManager.getProfile(new ProfileListener()); }
-
onSuccess
をProfileListener
に実装します。onSuccess
には主に2つのタスクがあります。レスポンスBundle
からプロファイルデータを取得することと、UIにデータを渡すことです。updateProfileData
は、プロファイルの詳細を表示するためにアプリが実装できる仮想関数です。setLoggedInState
はもう1つの仮想関数で、ユーザーがログイン中であることを示し、ログアウトの手段を提供します。Bundle
からプロファイルデータを取得するには、AuthzConstants
クラスによって格納される名前を使用します。onSuccess
バンドルでは、BUNDLE_KEY.PROFILE
バンドルにプロファイルデータが含まれます。プロファイルバンドル内で、スコープデータがPROFILE_KEY.NAME
、PROFILE_KEY.EMAIL
、PROFILE_KEY.USER_ID
、PROFILE_KEY.POSTAL_CODE
の下にインデックス付けされます。PROFILE_KEY.POSTAL_CODE
が返されるのは、postal_code
スコープがリクエストされた場合のみです。@Override public void onSuccess(Bundle response) { // バンドルから必要なデータを取得 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); } }); }
-
onError
をProfileListener
に実装します。onError
には、エラーの情報を含むAuthError
オブジェクトが入ります。/* プロファイルの取得中にエラーが発生。 */ @Override public void onError(AuthError ae) { /* 再試行するか、ユーザーにエラーを通知 */ }
-
onError
をAuthorizeListener
に実装します。/* アプリの認可中にエラーが発生。 */ @Override public void onError(AuthError ae) { /* ユーザーにエラーを通知 */ }
-
onCancel
をAuthorizeListener
に実装します。認可プロセスでは、ウェブブラウザ(またはWebView)を使用中のユーザーにログイン画面(場合によっては同意画面も)が表示されます。これに伴い、ユーザーがログインをキャンセルしたり別の画面に移動したりできる環境も整えておきます。ユーザーが明示的にログインプロセスをキャンセルする場合には、onCancel
が呼び出されます。onCancel
が呼び出される場合は、UIをリセットする必要があります。/* 完了前に認可がキャンセル。 */ @Override public void onCancel(Bundle cause) { /* UIをready-to-loginの状態にリセット */ }
注: ユーザーがブラウザやWebViewのログイン画面から離れてアプリに戻る場合、SDKではログインが未完了であることを検出しません。ログインの完了前にアプリでユーザーのアクティビティが検出された場合にはユーザーがブラウザから離れたと考えられるため、それに応じた対応を取ります。
起動時のユーザーログインの確認
アプリにログインしたユーザーが、アプリをいったん終了した後で再度アプリを起動させた場合、アプリは引き続きデータを取得できます。ユーザーが自動的にログアウトされることはありません。起動時にアプリが認可されていれば、ユーザーにログイン後の状態を表示できます。このセクションではgetToken
を使用して、アプリがまだ認可されているかどうかを確認する方法について説明します。
-
TokenListener
を作成します。TokenListener
はAPIListener
インターフェイスを実装し、getToken
の呼び出しの結果を処理します。APIListener
にはonSuccess
とonError
の2つのメソッドが含まれます(getToken
の呼び出しをキャンセルする手段がないため、onCancelはサポートされていません)。onSuccess
はトークンデータを含むBundle
オブジェクトを受け取ります。onError
はエラーの情報を含むAuthError
オブジェクトを受け取ります。private class TokenListener implements APIListener{ /* getTokenが正常に完了。 */ @Override public void onSuccess(Bundle response) { } /* トークンの取得中にエラーが発生。 */ @Override public void onError(AuthError ae) { } }
-
Activity
のonStart
メソッドで、getToken
を呼び出して、アプリがまだ認可されているかどうかを確認します。getToken
は未処理のアクセストークンを受け取り、AmazonAuthorizationManager
はそれを使用してユーザープロファイルにアクセスします。トークンの値がnull
でなければ、アプリはまだ認可されている状態であり、getProfile
への呼び出しが成功します。getToken
には、authorize
に対する呼び出しでリクエストした同じスコープが必要です。getToken
はgetProfile
と同じ方法で非同期呼び出しをサポートします。したがって、UIスレッドをブロックしたり、独自のワーカースレッドを作成したりする必要がありません。getToken
を非同期的に呼び出すには、APIListener
インターフェイスをサポートするオブジェクトを最後のパラメーターとして渡します。@Override protected void onStart(){ super.onStart(); mAuthManager.getToken(new String []{"profile","postal_code"}, new TokenListener()); }
-
onSuccess
をTokenListener
に実装します。onSuccess
には2つのタスクがあります。Bundle
からトークンを取得することと、トークンが有効な場合にgetProfile
を呼び出すことです。Bundle
からトークンデータを取得するには、AuthzConstants
クラスによって格納される名前を使用します。onSuccess
バンドルでは、BUNDLE_KEY.TOKEN
値にトークンデータが含まれます。その値がnullでなければ、この例は、前のセクション(手順7、8参照)で宣言したものと同じリスナーを使用してgetProfile
を呼び出します。/* getTokenが正常に完了。 */ @Override public void onSuccess(Bundle response) { final String authzToken = response.getString(AuthzConstants.BUNDLE_KEY.TOKEN.val); if (!TextUtils.isEmpty(authzToken)) { // プロファイルデータを取得 mAuthManager.getProfile(new ProfileListener()); } }
認可状態の消去とユーザーのログアウト
clearAuthorizationState
メソッドは、AmazonAuthorizationManager
ローカルデータストアからユーザーの認可データを消去します。この後でアプリがプロファイルデータを取得するには、ユーザーが再度ログインする必要があります。このメソッドを使用するのは、ユーザーをログアウトする場合、またはアプリのログイン問題をトラブルシューティングする場合です。
- ログアウトのメカニズムを実装します。ユーザーがログインに成功した後、ログアウトのメカニズムを提供してユーザーがプロファイルデータと過去の認可済みのスコープを消去できるようにします。ログアウトのメカニズムとして、ハイパーリンクやメニューアイテムを使用できます。この例では、ボタンの
onClick
メソッドを作成します。 - ログアウトハンドラーで
clearAuthorizationState
を呼び出します。clearAuthorizationState
はユーザーの認可データ(アクセストークン、プロファイル)をローカルストアから削除します。clearAuthorizationState
は、成功または失敗を返すAPIListener
以外のパラメーターは受け取りません。 - 匿名の
APIListener
を宣言します。匿名クラスは、APIListener
を実装する新しいクラスを宣言するための便利な代替クラスです。 onSuccess
をAPIListener
内に実装します。clearAuthorizationState
に成功すると、UIをアップデートしてユーザーの参照を削除し、ユーザーが再度ログインできるようにログインメカニズムを提供する必要があります。onError
をAPIListener
内に実装します。clearAuthorizationState
がエラーを返した場合は、ユーザーがログアウトを再試行できるようにします。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* 以前のonCreate宣言の省略 */
// ログアウトIDのボタンを検索してクリックハンドラーをセットアップ
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) {
// UIにログアウト状態を設定
}
@Override
public void onError(AuthError authError) {
// エラーをログに記録
}
});
}
});
}
AmazonAuthorizationManagerメソッドの同期的な呼び出し
一部のAmazonAuthorizationManager
メソッドはFuture
オブジェクトを返します。これにより、メソッドを同期的に呼び出すことができるため、パラメーターとしてリスナーを渡す必要がなくなります。Future
を使用する場合、UIスレッドではこのオブジェクトを使用しないでください。UIスレッドを5秒以上ブロックする場合は、「ANR」(アプリが応答していません)のメッセージが表示されます。上記の「ログインボタンの処理とプロファイルデータの取得」の例では、AmazonAuthorizationManager
によって作成されたワーカースレッドでAuthorizeListener
のonSuccess
メソッドが呼び出されます。つまり、このスレッドを使用して、getProfile
を同期的に呼び出すことができます。同期呼び出しを行うには、getProfile
からの戻り値をFuture
オブジェクトに割り当て、このオブジェクトでget
メソッドを呼び出してメソッドが終了するまで待機します。
Future.get
は、FUTURE_TYPE
値(SUCCESS
、ERROR
、またはCANCEL
)が含まれるBundle
オブジェクトを返します。メソッドが成功した場合は、同じバンドルにプロファイルデータのPROFILE_KEY
の値が返されます。次に例を示します。
/* 認可が正常に完了。 */
@Override
public void onSuccess(Bundle response) {
Future<Bundle> future = mAuthManager.getProfile(null);
Bundle result = future.get();
// 呼び出しが成功したかどうかを確認し、プロファイルを取得
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)
{
// エラーオブジェクトを取得
AuthError authError = AuthError.extractError(result);
/* authErrorを使用してエラーを診断 */
}
else if (future_type == AuthzConstants.FUTURE_TYPE.CANCEL)
{
/* ユーザーが認可中にキャンセル */
}
}