now.ggログインの統合

このページの手順に従って、now.ggログインをAndroidアプリに統合、設定し、ログインフローを開始するnow.ggサインインボタンをアプリのレイアウトに追加してください。

開始する前に

必須要項のチェックリストと開発環境のセットアップが完了していることを確認してください。

許可とアセットの追加

1. AndroidManifest.xmlに許可を追加する
 <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
  <uses-permission android:name="android.permission.INTERNET"/> 
2. アプリケーションの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'
3. now.ggサインインボタンを追加する
  1. now.ggサインインボタンのリソースアセットをダウンロードします。
  2. アプリケーションのレイアウトにnow.ggサインインボタンを追加します。
    Button signInButton = findViewById(R.id.now_gg_login_button);
    
  3. Androidのアクティビティ(例えばonCreateメソッド)で、ボタンのOnClickListenerを登録し、クリック時にサインインするようにします。
    findViewById(R.id.now_gg_login_button).setOnClickListener(this);

重要な情報

  • ユーザーが既にアプリでnow.ggアカウントでログインしている場合、その情報をアプリのデータベースに保存し、ユーザーがアプリを再度起動したときにログインプロセスをスキップするために使用する必要があります。
  • アプリに自動ログインを実装し、ログインボタンのフローをスキップしたい場合は、以下の3番目のステップ(now.ggアカウントでサインインするためのコード)で説明するように、signIn()関数を直接実装することで実現できます。

ログインフローの開始

1. サインインボタンタップの実行

AndroidアクティビティのonClickメソッドで、now.ggアカウントにログインしてサインインボタンタップを実行できます。

@Override
 public void onClick(View v) {
    switch (v.getId()) {
        case R.id.now_gg_login_button:
             signIn();
             break;
          // ...
    }
 }
2. View.OnClickListenerを実装し、GET_ACCOUNTS許可を確認する
メインのアクティビティに、implements 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.
             }
         }
     }
    

ユーザー情報とセッション情報の取得

  • また、now.ggログイン統合のための高度でより安全な認証コードフローも提供しています。
  • このフローでは、詳細なユーザー情報とセッション情報を取得することができます。
  • 上記の手順を完了したら、このセクションに移動し、Authコードフローを使用してnow.ggログインを実装します。
  • ユーザーがサインインした後に基本的なプロフィール情報のみを取得したい場合は、以下の手順に進んでください。

基本的なログインフローを続行する

3. 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 > 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();
     }
  }
4. ユーザーがサインインした後、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);
            // 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();
          }
     }
 }
5. ユーザーのIDトークンを検証し、ユーザーの詳細を取得する

ここで、(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_TOKENINVALID_TOKENなどのレスポンスが返ってきた場合は、signIn関数を再度呼び出すことで新しいトークンを要求することができます。
  • 現在サインインしているユーザーをバックエンドサーバーに渡すには、IDトークンをバックエンドサーバーに送信し、それを検証する必要があります。バックエンドサーバとの認証を参照ください。
×
テキストがクリップボードにコピーされました。
copyLinkText
ご不明な点がございましたら、お気軽にお問い合わせください。 dev-support@now.gg