このページの手順に従って、now.ggログインをAndroidアプリに統合、設定し、ログインフローを開始するnow.ggサインインボタンをアプリのレイアウトに追加してください。
必須要項のチェックリストと開発環境のセットアップが完了していることを確認してください。
まず、AndroidManifest.xml
に権限を追加します。
<uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="android.permission.INTERNET"/>
次の依存関係をアプリケーションの build.gradle
ファイルに追加してください:
//retrofit implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0' implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
now.ggサインインボタンのアセットは、now.gg SDKパッケージのAssets/Login
ディレクトリに含まれています。
Button signInButton = findViewById(R.id.now_gg_login_button);
Android アクティビティの onCreate
メソッドに、サインイン ボタンの OnClickListener
を追加します。
findViewById(R.id.now_gg_login_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { signIn(); } });
次に、GET_ACCOUNTS
権限と結果を確認してください。
GET_ACCOUNTS
許可を確認するには、onCreate
メソッドに以下のコードを追加します。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (checkSelfPermission(Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[] { Manifest.permission.GET_ACCOUNTS }, GET_ACCOUNTS_REQUEST_CODE); } else { // has GET_ACCOUNTS permission, can proceed with signin Log.d(TAG, "onCreate: Already has permission, proceed with signin"); } }
onRequestPermissionsResult
に以下のコードを追加します。
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == GET_ACCOUNTS_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission granted, can proceed with sign-in. signIn(); } } }
次のコードサンプルは「now.gg アカウントでサインインする」ためのものです。ログインボタンをクリックするとトリガーされるべきです。
public static final String ID_TOKEN = "id_token"; // Do Not Modify public static final String CLIENT_ID = "<your client id>"; // Replace with your client id public static final String ACCOUNT_TYPE = "now.gg"; // Do Not Modify public static final String HOST_URL = "hostUrl"; //Do Not Modify private void signIn() { Account account = getNowggAccount(); if (account != null) { Bundle bundle = new Bundle(); bundle.putString("client_id", CLIENT_ID); String authTokenType = ID_TOKEN; AccountManager.get(getApplicationContext()). getAuthToken(account, authTokenType, bundle, MainActivity.this, new OnTokenAcquired(), null); } else { addNowggAccount(); } } private Account getNowggAccount() { Account[] accounts = AccountManager.get(getApplicationContext()).getAccountsByType(ACCOUNT_TYPE); if (accounts.length & gt; 0) { Log.d(TAG, "getNowggAccount: account found"); // currently only one now.gg account can be added in a system return accounts[0]; } return null; } private void addNowggAccount() { try { Intent intent = new Intent(); intent.setComponent(new ComponentName("gg.now.accounts", "gg.now.accounts.AuthenticatorActivity")); intent.setAction("IAP_ADD_ACCOUNT"); intent.putExtra("resultReceiver", parcelResultReceiver(resultReceiver)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } catch (ActivityNotFoundException e) { e.printStackTrace(); } } ResultReceiver parcelResultReceiver(ResultReceiver actualReceiver) { Parcel parcel = Parcel.obtain(); actualReceiver.writeToParcel(parcel, 0); parcel.setDataPosition(0); ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel); parcel.recycle(); return receiverForSending; } ResultReceiver resultReceiver = new ResultReceiver(new Handler(Looper.getMainLooper())) { @Override protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); Log.d(TAG, "onReceiveResult() called with: resultCode = [" + resultCode + "], resultData = [" + resultData.toString() + "]"); // onReceiveResult if (resultCode == 0) { // means sign in is okay signIn(); } else { // sign in failed Log.d(TAG, "onReceiveResult: sign in failed"); } } };
ユーザーがサインインした後、OnTokenAcquired
コールバック関数でリクエストされたトークン (id_token) を取得します。
このトークンは、トークンを検証するか、トークンをバックエンドサーバーに渡してユーザーの詳細を取得するために使用できます。サーバーから応答としてユーザーの詳細を取得できます。
private class OnTokenAcquired implements AccountManagerCallback { @Override public void run(AccountManagerFuture result) { try { Bundle bundle = (Bundle) result.getResult(); boolean success = bundle.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false); if (success) { final String token = bundle.getString(ID_TOKEN); // now.ggのサーバーURLを取得し、ユーザーの詳細を取得し、トークンを検証します final String hostUrl = bundle.getString(HOST_URL); verifyToken(token, hostUrl); } else { // トークンの取得に失敗しました // エラーの場合。開発者はエラーを表示するか、他のログイン方法を表示できます Log.d(TAG, "run: get token failed " + bundle); } } catch (AuthenticatorException | IOException | OperationCanceledException e) { e.printStackTrace(); } } }
次に、OnTokenAcquired
で受け取った id_token
の整合性を verifyToken
関数を呼び出して検証し、以下のようにユーザーの詳細を取得する必要があります:
private void verifyToken(String idToken, String hostUrl) { BackendApiCallService backendApiCallService = getBackendRetrofit(hostUrl).create(BackendApiCallService.class); Call < TokenVerifyResponse > tokenVerifyResponseCall = backendApiCallService.verifyIdToken(new TokenVerifyRequest(ID_TOKEN, idToken, CLIENT_ID)); tokenVerifyResponseCall.enqueue(new Callback < TokenVerifyResponse > () { @Override public void onResponse(Call < TokenVerifyResponse > call, Response < TokenVerifyResponse > response) { if (response.isSuccessful()) { Log.d(TAG, "onResponse: " + response.body().toString()); } else { Gson gson = new Gson(); TokenVerifyResponse error = gson.fromJson(response.errorBody().charStream(), TokenVerifyResponse.class); if (!error.isSuccess() && ("EXPIRED_TOKEN".equals(error.getCode()) || "INVALID_TOKEN".equals(error.getCode()))) { // retry the verify token call, after getting a new TOKEN } } } @Override public void onFailure(Call call, Throwable t) { Log.d(TAG, "onFailure() called with: call = [" + call + "], t = [" + t + "]"); } }); } public Retrofit getBackendRetrofit(String hostUrl) { OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); return new Retrofit.Builder() .baseUrl(hostUrl) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .client(okHttpClient) .build(); } public interface BackendApiCallService { @POST("/accounts/oauth2/v1/verify-token") Call < TokenVerifyResponse > verifyIdToken(@Body TokenVerifyRequest authRequest); } public class TokenVerifyRequest { String token_type; String token; String client_id; public TokenVerifyRequest(String token_type, String token, String client_id) { this.token_type = token_type; this.token = token; this.client_id = client_id; } } public class TokenVerifyResponse { boolean success; String code; String msg; @SerializedName("decodedData") UserDataVerified userDataVerified; public TokenVerifyResponse(boolean success, String code, String msg, UserDataVerified userDataVerified) { this.success = success; this.code = code; this.msg = msg; this.userDataVerified = userDataVerified; } public UserDataVerified getUserDataVerified() { return userDataVerified; } public boolean isSuccess() { return success; } public String getCode() { return code; } @Override public String toString() { return "TokenVerifyResponse{" + "success=" + success + ", code='" + code + '\'' + ", msg='" + msg + '\'' + ", userDataVerified=" + userDataVerified + '}'; } }
UserDataVerifiedクラスの詳細については、プロファイル情報の取得セクションを参照してください。
注意:
EXPIRED_TOKEN
やINVALID_TOKEN
などのレスポンスが返ってきた場合は、signIn
関数を再度呼び出すことで新しいトークンを要求することができます。このセクションでは、ユーザーのログアウトを実装する方法を説明します。
ユーザーのログアウトを実行するには:
以下のセクションでは、取得したユーザープロフィール情報の使用プロセスを説明します。
id_token
を取得します。OnTokenAcquired
で受け取ったユーザー情報を取得するには、verifyToken
関数を呼び出す必要があります。アプリにバックエンドサーバーがない場合は、以下のセクションを使用してユーザープロファイル情報を取得できます。
デバイス上のAPI呼び出しを使用して、ログインしているユーザーのプロファイル情報を取得できます。これを行うには、verifyToken
関数を呼び出して受信したTokenVerifyResponse
の userDataVerified
フィールドを使用します。
UserDataVerified userData = tokenVerifyResponse.getUserDataVerified(); String userId = userData.getUserId(); String name = userData.getName(); String email = userData.getEmail(); String picture = userData.getPicture(); public class UserDataVerified { String iss; String sub; String aud; String exp; String iat; String auth_time; String tokenId; String sessionId; String scope; String email; String name; String picture; String mobile; String userId; public UserDataVerified(String iss, String sub, String aud, String exp, String iat, String auth_time, String email, String mobile, String userId, String tokenId, String sessionId, String scope, String name, String picture) { this.iss = iss; this.sub = sub; this.aud = aud; this.exp = exp; this.iat = iat; this.auth_time = auth_time; this.email = email; this.mobile = mobile; this.userId = userId; this.tokenId = tokenId; this.sessionId = sessionId; this.scope = scope; this.name = name; this.picture = picture; } @Override public String toString() { return "UserDataVerified{" + "iss='" + iss + '\'' + ", sub='" + sub + '\'' + ", aud='" + aud + '\'' + ", exp='" + exp + '\'' + ", iat='" + iat + '\'' + ", auth_time='" + auth_time + '\'' + ", tokenId='" + tokenId + '\'' + ", sessionId='" + sessionId + '\'' + ", scope='" + scope + '\'' + ", email='" + email + '\'' + ", name='" + name + '\'' + ", picture='" + picture + '\'' + ", mobile='" + mobile + '\'' + ", userId='" + userId + '\'' + '}'; } }
userData.getUserId()
を使用してuserId
を取得できます。userId
を取得できます。ユーザーアカウントサービス
ユーザーアカウントサービス
ドキュメント改訂版 1.0