このページの手順に従って、now.ggログインをAndroidアプリに統合、設定し、ログインフローを開始するnow.ggサインインボタンをアプリのレイアウトに追加してください。
必須要項のチェックリストと開発環境のセットアップが完了していることを確認してください。
<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'
Button signInButton = findViewById(R.id.now_gg_login_button);
onCreate
メソッド)で、ボタンのOnClickListener
を登録し、クリック時にサインインするようにします。
findViewById(R.id.now_gg_login_button).setOnClickListener(this);
signIn()
関数を直接実装することで実現できます。AndroidアクティビティのonClick
メソッドで、now.ggアカウントにログインしてサインインボタンタップを実行できます。
@Override public void onClick(View v) { switch (v.getId()) { case R.id.now_gg_login_button: signIn(); break; // ... } }
View.OnClickListener
を追加し、GET_ACCOUNTS
許可を確認します。private final int GET_ACCOUNTS_REQUEST_CODE = 100; public class MainActivity extends AppCompatActivity implements View.OnClickListener { }
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. } } }
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 > 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.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } catch (ActivityNotFoundException e) { e.printStackTrace(); } }
このトークンを使用して、トークンを検証するか、トークンをバックエンドサーバーに渡して、ユーザーの詳細を取得することができます。サーバーからのレスポンスとして、ユーザーの詳細情報を取得します。
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); // get the now.gg server URL, from which you can get the user details and verify the tokens final String hostUrl = bundle.getString(HOST_URL); verifyToken(token, hostUrl); } else { // get token failed // error case. The developer can show errors or show other login mechanisms 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
関数を再度呼び出すことで新しいトークンを要求することができます。ドキュメント改訂版 1.0