Login Module for Native Android

Follow the steps on this page to integrate now.gg Login into your Android app, configure it and add the now.gg Sign-in button to your app’s layout that starts the login flow.

Before you start

Make sure you have completed the prerequisites checklist and set up your developer environment.

Add Permissions, Dependencies and Assets

1. Add permissions

Start by adding the permissions to AndroidManifest.xml.

 <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
  <uses-permission android:name="android.permission.INTERNET"/> 

2. Add dependencies

Add the following dependencies in your application build.gradle file:

//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. Show now.gg Sign-in Button

3.1 Download the now.gg Sign-in Button Assets

The now.gg Sign-in button assets are included within now.gg SDK package under the Assets/Login directory.

3.2 Choose a Sign-in Button Option
  • Recommended Sign-in Button: Use the provided button assets for a standard look and feel.
  • Custom Sign-in Button: Create a custom “Sign in with now.gg” button using the provided logo-only asset and your own text to design a button that fits your app’s style.
3.3 Add the ‘now.gg Sign-in button’ in your application’s layout:
Button signInButton = findViewById(R.id.now_gg_login_button);

Important Information

  • You must display the ‘now.gg Sign-in Button’ and on-click trigger the login during the user’s initial login. For subsequent logins, save the user’s information in your app’s database or shared preferences to skip the login process.


Start the Login Flow

1. Add OnClick Event to Sign-in button

In the Android activity’s onCreate method, add OnClickListener for the sign-in button.

 findViewById(R.id.now_gg_login_button).setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {
         signIn();
     }
 });

2. Check Permission and Results

You should now check for the GET_ACCOUNTS permission and Results.

  • To check for GET_ACCOUNTS permission, add the following code to your onCreate method:
    @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");
         }
     }
    
  • To check for results, add the following code to your 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();
             }
         }
     }
    

Get User and Session Information

  • We also offer an advanced and more secure Auth Code Flow for now.gg Login integration.
    • This flow enables you to get detailed user and session information.
    • After you have completed the steps above, navigate to this section to implement now.gg Login using Auth Code flow.
  • If you only wish to fetch basic profile information after the user sign-in, you can continue with the steps below.

Continue with Basic Login Flow


3. Perform Sign-in

The following code sample is to perform ‘Sign-in with now.gg Account’, which should be triggered on the click of the Login Button.

 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");
          }
      }
  };

4. Get Requested Token

After the user signs in, you will get the requested token (id_token) in OnTokenAcquired callback function. This token can be used to get the user’s details by verifying the token or passing the token to your backend server. You will get the user details from your server as a response.

      
 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. Validate Token and Get User Details

Now, you have to verify the integrity of id_token (that you received in OnTokenAcquired) by calling the verifyToken function and get the user’s details, as illustrated below:

     
  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 +
       '}';
   }
 }

For more information on the UserDataVerified class, please refer to the Retrieve Profile Information section.

Note:

  • If you get responses such as EXPIRED_TOKEN or INVALID_TOKEN, you can request a new token by calling the signIn function again.
  • To pass the currently signed-in user to a backend server, you should send the ID token to your backend server and validate it. See – Authenticate with a backend server.
  • Once a user logs in, save the login information in your app’s local database or shared preferences to ensure that the user can continue with the game automatically on subsequent launches without re-triggering the login flow.

6. Implement User Logout -Optional

This section illustrates how to implement logout for your users.

To perform log out for a user:

  • Remove their saved login information from the app’s local database/shared preferences and display the login screen again.
  • After logging out, the user can continue playing as a guest or use any other login options available in your game.



Using Profile Information

The following section illustrates the process of using the retrieved profile information of the user.

After you have signed in the user with a now.gg account, you now have the id_token. To get user details that you received in OnTokenAcquired, you have to call the verifyToken function.
If your app has a backend server and you wish to fetch the User Profile for a signed-in user at your backend, please refer to this section.

Warning

  • Do not use a user’s email address or user ID to communicate the currently signed-in user to your app’s backend server. Instead, send the user’s ID token to your backend server and validate the token on the server.

If your app does not have a backend server, you can use the following section to retrieve user profile information.

Retrieve profile information

You can get the profile information for a logged-in user, using an on-device API call. To do this, use the userDataVerified field from the TokenVerifyResponse that you received by calling the verifyToken function.

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 + '\'' +
               '}';
   }
 }         
Once you have the user details, you should save that information in your app’s database and use it to skip the login process next time the user launches your app.

Important Information

  • It is recommended that you don’t use the email address to identify a user. Instead, use the userId.
  • If your app does not have a backend server, you can get the userId on the client using userData.getUserId().
  • If your app has a backend server, you can call the verify token API and get the userId as a response with the user data.

×

User Account Service

Login Module for Native Android

User Account Service

Document Rev. 1.0

Text copied to clipboard
Link copied to clipbord
Questions? Please reach out to us at dev-support@now.gg