Skip to content

Login logout

Login logout

Note
  • Helper is provided with SDK v4.7.0. To use earlier than SDK 4.7.0, see this page.
  • For more description about AuthV4.Helper, refer to Authentication page.

Login

Login in authentication is composed of the following steps.

  1. Automatic Login and Implicit Login
  2. Explicit Login
  3. Checking Logged-in IdP Account on Device
  4. Guest Login

Authv4Helper executes some part of login process, and indicates the proper page based on the response.

Refer to the following notes to implement the login function.

Note

Apple does not support Apple Game Center and in-app for iOS Enterprise Builds. Therefore, it is unavailable to use Implicit Login using Apple Game Center account in iOS Enterprise Build, and unavailable to use Apple Game Center in the state of Explicit Login.

Note
Note
  • In China, Implicit Login is not available on Android because Google Play Games is prohibited in the country.
  • Facebook is not included in the IdP lists as Facebook is not available in China.
  • If users access the game with Chinese IP, only authorized members can charge game money or purchase items (started from May 1, 2017). Therefore, In Chinese IP, Guest Login is excluded from IdP lists that can log in.
Note

iOS does not display login screen when sign-in to Apple Game Center is cancelled. Therefore, notification phrases can be displayed by implementing showGameCenterLoginCancelDialog() method in the AuthV4Helper class directly from SDK or by game studio. In case the callback result of AuthV4.signIn(AuthV4.ProviderType.APPLE, ...) and that of AuthV4.connect(AuthV4.ProviderType.APPLE, ...) are Cancel, Notification phrases for Game Center Sign-in Disabled is available. Provide the phrases to guide users how to sync with Game Center account again.

Note

If sign-in with Apple is tried without sign-in with Apple ID on user device, AuthV4SignInAppleUnknown error is occurred while calling connect() and signIn() method in the AuthV4Helper class. In this case, a notice popup for sign-in with Apple ID is exposed automatically, therefore, game studios have nothing to call.

Automatic login and implicit login

Automatic login

Implicit Login is a method that the user does not select a means of login, but logs in the Apple Game Center account on iOS or the Google Play Games account on Android automatically. Implement the Implicit Login to be executed after failure of Automatic Login.

Offline mode

Hive SDK v4 23.1.0 and higher offers an automatic login feature (AuthV4.signIn using ProviderType.AUTO, or AuthV4.Helper.signIn) even when the user's device is not connected to the network. To use the offline mode, follow the instructions below:

  1. It is necessary that the app was run in online mode at least once, resulting in a successful explicit, implicit, guest, or custom login, and subsequently, playerId and playerToken were issued.
    From the perspective of the app developers, there must have been at least one successful execution of AuthV4.Helper.signIn, AuthV4.showSignIn, or AuthV4.signInWithAuthKey in an online state, with the reception of playerId and playerToken via callback. From the user's perspective, they must have successfully logged into the app at least once while their device was connected to the network. However, if the user's account was suspended or restricted during their last login attempt in online mode, they will not be able to log in in offline mode.

  2. Activate the offline mode in the Hive Console under App Center > Manage Project > Game Details > Hive Product Settings.

Automatic login on Windows

Windows environment supports automatic login, and it can be enabled/disabled in the Hive Console App Center. Note that the Windows automatic login works differently from the automatic login for the mobile environment. The differences are:

  • In the mobile environment, a user is kept logged in by automatic login, but in Windows, it is kept only when a user enabled “keep me logged in” checkbox (displayed below the IdP list in login UI). In other circumstances, the login status does not continue.
  • In the mobile environment, when you execute AuthV4Helper.Connect and convert to another account, the newly logged in account also is kept logged in by the automatic login, but in Windows, it is not.

Implicit login

  • Login flow of Implicit Login

AuthV4.Helper.signIn tries Automatic Login by using the authentication token key of PlayerID. If the token key generated from previous login does not exist, the game automatically sign in Apple Game Center for iOS, and Google Play Games for Android. If failed to sign in, it displays a proper login page in accordance with the response.

Note

In case of implementing AuthV4Helper class,

  • If user cancelled implicit login to PGS while loading a game, system memorizes the status and does not try implicit login again. Even if auto login is available while player session is valid, the system remember the denied state.

This contents comply with Google Play Games Services guide.

Followings are sample codes to execute Automatic Login.

API Reference: hive.AuthV4.Helper.signIn

// Attempt Hive SDK login (signIn)
AuthV4.Helper.signIn (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {

if (result.isSuccess()) {
// log-in succeed
} else if (result.needExit()) {
// TODO: implement app exit functionality
// Example) Application.Quit();
} else {
switch(result.code) {
case ResultAPI.Code.AuthV4ConflictPlayer:
// account conflict
break;
case ResultAPI.Code.AuthV4HelperImplifiedLoginFail:
// implicit login failed
// ex) AuthV4.showSignIn(...);
break;
default:
// other exceptions
break;
}
}
});
#include "HiveAuthV4.h"

// Attempt Hive SDK login (signIn)
FHiveAuthV4::Helper::SignIn(FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TOptional<FHivePlayerInfo>& PlayerInfo) {
        if (Result.IsSuccess()) {
                //log-in succeed
        } else if (Result.NeedExit()) {
    // TODO: implement app exit functionality
// Users of the Cocos2d-x engine
// ex) exit(0);
// Unreal engine users
// Example) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        } else {
                switch (Result.Code) {
                        case FHiveResultAPI::ECode::AuthV4ConflictPlayer:
                                // account conflict
                                break;
                        case FHiveResultAPI::ECode::AuthV4HelperImplifiedLoginFail:
                                // implicit login failed
                                // ex) AuthV4.showSignIn(...);)
                                break;
                        default:
                                // other exceptions
                                break;
                }
        }
}));

API Reference: Auth4::signIn

// Attempt Hive SDK login (signIn)
AuthV4::Helper::signIn([=](ResultAPI const & result, std::shared\_ptr playerInfo) {

if (result.isSuccess()) {
// log-in succeed
} else if (result.needExit()) {
// TODO: implement app exit functionality
// Users of the Cocos2d-x engine
// ex) exit(0);
// Unreal engine users
// Example) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
} else {
switch(result.code) {
case ResultAPI::AuthV4ConflictPlayer:
// account conflict
break;
case ResultAPI::AuthV4HelperImplifiedLoginFail:
// implicit login failed
// ex) AuthV4.showSignIn(...);
break;
default:
break;
}
}
});

API Reference: com.hive.Auth4.Helper.signIn

// Attempt Hive SDK login (signIn)
AuthV4.Helper.signIn(object : AuthV4.Helper.AuthV4HelperListener {
    override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        if (result.isSuccess) {
            // log-in succeed
        } else if (result.needExit()) {
            // TODO: implement app exit functionality
            // ex) exitProcess(0)
        } else {
            when (result.code) {
                ResultAPI.Code.AuthV4ConflictPlayer -> {
                    // account conflict
                }
                ResultAPI.Code.AuthV4HelperImplifiedLoginFail -> {
                    // implicit login failed
                    // ex) AuthV4.showSignIn(...);
                }
                else -> {
                    // other exceptions
                }
            }
        }
    }
})

API Reference: com.hive.Auth4.signIn

// Attempt Hive SDK login (signIn)
AuthV4.Helper.signIn(new AuthV4.Helper.AuthV4HelperListener() {
    @Override
    public void onAuthV4Helper(ResultAPI result, AuthV4.PlayerInfo playerInfo) {

        if (result.isSuccess()) {
            // log-in succeed
        } else if (result.needExit()) {
            // TODO: implement app exit functionality
            // ex) System.exit(0);
        } else {
            switch(result.code) {
                case AuthV4ConflictPlayer:
                    // account conflict
                    break;
                case AuthV4HelperImplifiedLoginFail:
                    // implicit login failed
                    // ex) AuthV4.showSignIn(...);
                    break;
                default:
                    // other exceptions
                    break;
            }
        }
    }
});

API Reference: AuthV4Interface.signIn

// Attempt Hive SDK login (signIn)
AuthV4Interface.helper().signIn() { (result, playerInfo) in

    if result.isSuccess() {
        // log-in succeed
    }
    else if result.needExit() {
        // TODO: implement app exit functionality
        // ex) exit(0)
    }
    else {
        switch result.getCode() {
        case .authV4ConflictPlayer:
            // account conflict
        case .authV4HelperImplifiedLoginFail:
            // implicit login failed
            // ex) AuthV4Interface.showSignIn() { (result, playerInfo)
            // // do something...
            // }
        default:
            // other exceptions
            break
        }
    }
}

API Reference: HIVEAuth4:signIn

// Attempt Hive SDK login (signIn)
[[HIVEAuthV4 helper] signIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {

    if (result. isSuccess) {
        // log-in succeed
    }
    else if (result. needExit) {
        // TODO: implement app exit functionality
        // ex) exit(0);
    }
    else {
        switch(result.code) {
            case kAuthV4ConflictPlayer:
                // account conflict
                break;
            case kAuthV4HelperImplifiedLoginFail:
                // implicit login failed
                // ex) [HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
                // // do something...
                // }];
                break;
            default:
                // other exceptions
                break;
        }
    }
}];

Implicit login behavior: mobile

On mobile platforms (Hive SDK Unity Android, etc., Android/iOS), implicit login (AuthV4.Helper.signIn) causes an account conflict and prompts the user with a dialog asking whether to log in with the last logged-in account after the initial login.

Implicit login behavior: PC

On PC platforms (Hive SDK Unity Windows, etc., Windows), implicit login (AuthV4.Helper.signIn) automatically logs in with the last logged-in account after the initial login, without causing any account conflict.

Explicit login

Explicit Login means a process that user chooses an IdP to proceed with authentication. If a player failed to execute both Automatic Login and Implicit Login, implement the game to make the player go to the game title screen and execute Explicit Login when tapping the title.

Explicit Login is composed of the UI provided by Hive SDK or the UI customized in games with the IdP lists returned after initializing Hive SDK used in authentication. If you customize the UI, see Customizing Explicit Login UI .

Hive platform controls and provides IdP lists in accordance with the policy of each country. For example, Google Play Games, Facebook, and Guest Login are not available in China.

An example screen of explicit Login

IdP selection UI provided by Hive SDK


When implementing the function with the UI provided by Hive SDK

To implement Explicit Login with the UI provided by Hive SDK, you can display the IdP list UI by calling showSignIn() method.

Note

Make sure to provide a method to sign in again after user taps X button to close in the IdP selection UI provided by the SDK. Because the user has not logged in yet.

Note

If you want to customize Explicit Login, see here.

API Reference: hive.AuthV4.showSignIn

<code>    
    // Request Hive SDK AuthV4 Authentication UI    
    AuthV4.showSignIn((ResultAPI result, AuthV4.PlayerInfo playerInfo)=>{    
    if (result.isSuccess()) {    
        // authentication success    
        // playerInfo : Authenticated user information    
        // the example of getting email information    
        foreach (KeyValuePair<AuthV4.ProviderType, AuthV4.ProviderInfo> entry in playerInfo.providerInfoData) {    

            AuthV4.ProviderInfo providerInfo = entry.Value;    
            if(providerInfo.providerEmail != null && providerInfo.providerEmail != "") {    
                string email = providerInfo.providerEmail;    
                break;    
            }    
        }    
    }    
    else if (result.needExit()) {    
        // TODO: Implement the termination of the app    
        // Example) Application.Quit();    
    }    
});
#include "HiveAuthV4.h"

// Request Hive SDK AuthV4 Authentication UI
FHiveAuthV4::ShowSignIn(FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {
        if (Result.IsSuccess()) {
                // authentication success 

                 // the example of getting email information
                for (const auto& ProviderInfoEntry : PlayerInfo.ProviderInfoData) {
                        FHiveProviderInfo ProviderInfo = ProviderInfoEntry.Value;
                        FString Email = ProviderInfo.ProviderEmail;
                }
        } else if (Result.NeedExit()) {
                // TODO: Implement the termination of the app    
        // Users of the Cocos2d-x engine    
        // ex) exit(0);    
        // Unreal engine users    
        // Example) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        }
}));

API Reference: AuthV4::showSignIn

// Request Hive SDK AuthV4 Authentication UI    
    AuthV4::showSignIn([=](ResultAPI const & result, PlayerInfo const & playerInfo) {    
    if (result.isSuccess()) {     
        // authentication success     
        // playerInfo: Authenticated user information    
        // the example of getting email information    
        for(auto it = playerInfo.providerInfoData.begin(); it != playerInfo.providerInfoData.end(); ++it) {    
            hive::ProviderInfo providerInfo = it->second;    
            if(!providerInfo.providerEmail.empty()) {    
                std::string email = providerInfo.providerEmail;    
                break;    
            }    
        }    
    }    
    else if (result.needExit()) {    
        // TODO: Implement the termination of the app    
        // Users of the Cocos2d-x engine    
        // ex) exit(0);    
        // Unreal engine users    
        // Example) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);    
    }    
});

API Reference: com.hive.AuthV4.showSignIn

// Request Hive SDK AuthV4 Authentication UI    
    AuthV4.showSignIn(object : AuthV4.AuthV4SignInListener {    
    override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {    
        if (result.isSuccess) {    
            // authentication Success    
            // playerInfo: Authenticated user information    
            // the example of getting email information    
            playerInfo?.let {    
                for ((key, value) in it.providerInfoData) {    
                    var providerInfo: AuthV4.ProviderInfo = value    
                    if(providerInfo.providerEmail.isNotEmpty()) {    
                        val email = providerInfo.providerEmail    
                        break    
                    }    
                }    
            }    
        } else if (result.needExit()) {    
            // TODO: Implement the termination of the app    
            // ex) exitProcess(0)    
        }    
    }    
})

API Reference: com.hive.AuthV4.showSignIn

// Request Hive SDK AuthV4 Authentication UI    
    AuthV4.showSignIn(new AuthV4.AuthV4SignInListener() {    
        @Override    
        public void onAuthV4SignIn(ResultAPI result, AuthV4.PlayerInfo playerInfo) {    
        if (result.isSuccess()) {    
            // authentication success    
            // playerInfo: Authenticated user information    
            // the example of getting email information    
            if(playerInfo != null) {    
                for (Map.Entry<AuthV4.ProviderType, AuthV4.ProviderInfo> entry : playerInfo.getProviderInfoData().entrySet()) {    
                    AuthV4.ProviderInfo providerInfo = entry.getValue();    
                    if (providerInfo.getProviderEmail() != "") {    
                        String email = providerInfo.getProviderEmail();    
                        break;    
                    }    
                }    
            }    
        }    
        else if (result.needExit()) {    
            // TODO: Implement the termination of the app    
            // Example) System.exit(0);    
        }    
    }    
});

API Reference: HIVEAuthV4:showSignIn

var email = String()    
    // Request Hive SDK AuthV4 Authentication UI    
    AuthV4Interface.showSignIn { (result, playerInfo) in    

    if result.isSuccess() {    
        // authentication success    
        // playerInfo: Authenticated user information    
        // the example of getting email information    
        if let playerInfo = playerInfo {    
            // find providerInfo that the providerEmail exists (the provider of the current sign-in)    
            for key in playerInfo.providerInfoData.keys {    
                if let providerInfo = playerInfo.providerInfoData[key],    
                    providerInfo.providerEmail.count > 0 {    
                    // providerEmail != ""    
                    email = providerInfo.providerEmail    
                    break    
                }    
            }    
        }    
    } else if result.needExit() {    
        // TODO: Implement the termination of the app    
        // ex) exit(0)    
    }    
}

API Reference: HIVEAuthV4:showSignIn

__block NSString* email = @"";    
    // Request Hive SDK AuthV4 Authentication UI    
    [HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {    
    if([result isSuccess]){    
        // authentication success    
        // playerInfo: Authenticated user information    
        // the example of getting email information    
        if(playerInfo != nil) {    
            // find providerInfo that the providerEmail exists (the provider of the current sign-in)    
            for (NSString* key in playerInfo.providerInfoData.allKeys) {    
                HIVEProviderInfo* providerInfo = playerInfo.providerInfoData[key];    
                if (providerInfo != nil && providerInfo.providerEmail.length > 0) {    
                    // providerEmail != ""    
                    email = providerInfo.providerEmail;    
                    break;    
                }    
            }    
        }    
    } else if ([result needExit]) {    
        // TODO: Implement the termination of the app    
        // Example) exit(0);    
    }    
}];

Customizing explicit login UI

You can implement a customized UI for an explicit login by using providerTypeList, which is returned as a callback handler of AuthV4.setup() method called for Hive SDK initialization, or AuthV4.Helper.getIDPList() method called after Hive SDK initialization. Customizing explicit login UI is used when you want to display the login screen according to the game UI, or to display the linking option with a specific IdP only. After designing the UI, call signIn() method with the desired ProviderType depending on the user's action.

Note
  • Example UI which exposes only Facebook-synced button on sign-in page

Followings are sample codes for the case that user selects Google sign-in on the customized explicit login UI.

API Reference: hive.AuthV4.signIn

using hive;    
    AuthV4.signIn(AuthV4.ProviderType.GOOGLE, (ResultAPI result, AuthV4.PlayerInfo playerInfo) => {    
         if (result.isSuccess()) {    
             // call successful    
             // playerInfo: Authenticated user information.    
             // Example of email information search for ProviderType.GOOGLE    
             Dictionary<AuthV4.ProviderType, AuthV4.ProviderInfo> providerInfoData = playerInfo.providerInfoData;    
             AuthV4.ProviderInfo providerInfo = providerInfoData[AuthV4.ProviderType.GOOGLE];    
             string email = providerInfo.providerEmail;    
         }    
});
#include "HiveAuthV4.h"

FHiveAuthV4::SignIn(EHiveProviderType::GOOGLE,
                                        FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {

        if (Result.IsSuccess()) {
                // call successful    
      // playerInfo: Authenticated user information.

                // Example of email information search for ProviderType::GOOGLE
                TMap<EHiveProviderType, FHiveProviderInfo> ProviderInfoData = PlayerInfo.ProviderInfoData;
                if (const FHiveProviderInfo* ProviderInfo = ProviderInfoData.Find(EHiveProviderType::GOOGLE)) {
                        FString Email = ProviderInfo->ProviderEmail;
                }
        }
}));

API Reference: Auth4::signIn

#include <HIVE_SDK_Plugin/HIVE_CPP.h>    
    AuthV4::signIn(ProviderType::GOOGLE, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {    
         if (result.isSuccess()) {    
             // call successful    
             // playerInfo: Authenticated user information.    

             // Example of email information search for ProviderType::GOOGLE    
             map<ProviderType, ProviderInfo> providerInfoData = playerInfo.providerInfoData;    
             ProviderInfo providerInfo = providerInfoData[ProviderType::GOOGLE];    
             string email = providerInfo.providerEmail;    
         }    
});

API Reference: AuthV4.signIn

import com.hive.AuthV4    
    import com.hive.ResultAPI    
    AuthV4.signIn(AuthV4.ProviderType.GOOGLE, object : AuthV4.AuthV4SignInListener {    
         override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {    
             if (result.isSuccess) {    
                 // call successful    
                 // playerInfo: Authenticated user information    
                 // Example of email information search for ProviderType.GOOGLE    
                 if (playerInfo != null) {    
                     val providerInfoData = playerInfo.providerInfoData    
                     val providerInfo = providerInfoData[AuthV4.ProviderType.GOOGLE]    
                     if (providerInfo != null) {    
                         val email = providerInfo.providerEmail    
                     }    
                 }    
             }    
         }    
})

API Reference: com.hive.Auth4.signIn

import com.hive.AuthV4;    
    import com.hive.ResultAPI;    
    AuthV4.INSTANCE.signIn(AuthV4.ProviderType.GOOGLE, (result, playerInfo) -> {    
         if (result.isSuccess()) {    
             // call successful    
             // playerInfo: Authenticated user information    
             // Example of email information search for ProviderType.GOOGLE    
             if (playerInfo != null) {    
                 HashMap<AuthV4.ProviderType, AuthV4.ProviderInfo> providerInfoData = playerInfo.getProviderInfoData();    
                 AuthV4.ProviderInfo providerInfo = providerInfoData.get(AuthV4.ProviderType.GOOGLE);    
                 if (providerInfo != null) {    
                     String email = providerInfo.getProviderEmail();    
                 }    
             }    
         }    
});

API Reference: AuthV4Interface.signIn

import HIVEService    
    AuthV4Interface.signIn(.Google) { result, playerInfo in    
        if result.isSuccess() {    
            // call successful    
             // playerInfo: Authenticated user information      

            // Example of email information search for ProviderType::GOOGLE  
            if     
                let playerInfo = playerInfo,    
                let providerInfo = playerInfo.providerInfoData["GOOGLE"] {    
                    let email = providerInfo.providerEmail    
            }    
        }    
}

API Reference: HIVEAuth4:signIn

#import <HIVEService/HIVEService-Swift.h>    
    [HIVEAuthV4 signIn:HIVEProviderTypeGoogle handler:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {    
         if ([result isSuccess]){    
             // call successful    
             // playerInfo: Authenticated user information.    

             // Example of email information search by HIVEProviderTypeGoogle    
             if(playerInfo != nil) {    
                 HIVEProviderInfo *providerInfo = playerInfo.providerInfoData[@"GOOGLE"];    
                 if(providerInfo != nil){    
                     NSString *email = providerInfo.providerEmail;    
                 }    
             }    
         }    
}];

Check logged-in IdP account on device

Automatic Login is available to sign in with the token key of registered playerId, and so as Explicit Login with various IdPs. In the case of these two cases, the IdP account (DevicePlayer) logged-in on user device may mismatch with the IdP of PlayerID, which user logged in. Considering the use of achievement or leaderboard, notification page is provided for users to match two accounts.

  • SDK-providing UI which asks whether to use DevicePlayer or not

Followings are sample codes to confirm the IdP information.

API Reference: AuthV4.Helper.syncAccount

using hive;    
    AuthV4.ProviderType providerType = AuthV4.ProviderType.GOOGLE;    
    AuthV4.Helper.syncAccount (providerType, delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {    

         switch (result.code) {    
             case ResultAPI.Code.Success:    
                 // normal    
                 break;    
             case ResultAPI.Code.AuthV4ConflictPlayer:    
                 // account conflict    
                 // ex) When using Hive UI   
                 // AuthV4.Helper.showConflict(...);    
                 //or    
                 // ex) When implementing GameUI    
                 // AuthV4.Helper.resolverConflict(...);// When selecting the current user    
                 // AuthV4.Helper.switchAccount(...);// When selecting user switch    
                 break;    
             default:    
                 // other exception situations    
                 break;    
         }    
});
#include "HiveAuthV4.h"

FHiveAuthV4::Helper::SyncAccount(ProviderType, FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TOptional<FHivePlayerInfo>& PlayerInfo) {

        switch (Result.Code) {
                case FHiveResultAPI::ECode::Success:
                        // normal
                        break;
                case FHiveResultAPI::ECode::AuthV4ConflictPlayer:
                        // account conflict    
                        // ex) When using Hive UI   
                        // AuthV4::Helper::showConflict(...);    
                        //or    
                        // ex) When implementing GameUI    
                        // AuthV4::Helper::resolverConflict(...);// When selecting the current user    
                        // AuthV4::Helper::switchAccount(...);// When switching user is selected
                        break;
                default:
                        // other exception situations
                        break;
        }
}));

API Reference: AuthV4 ::Helper::syncAccount

#include <HIVE_SDK_Plugin/HIVE_CPP.h>    
    using namespace std;    
    using namespace hive;    
    ProviderType providerType = ProviderType::GOOGLE;    
    AuthV4::Helper::syncAccount(providerType, [=](ResultAPI const & result, shared_ptr<PlayerInfo> playerInfo) {    

         switch (result.code) {    
           case ResultAPI::Success:    
             // normal    
             break;    
           case ResultAPI::AuthV4ConflictPlayer:    
             // account conflict    
             // ex) When using Hive UI   
             // AuthV4::Helper::showConflict(...);    
             //or    
             // ex) When implementing GameUI    
             // AuthV4::Helper::resolverConflict(...);// When selecting the current user    
             // AuthV4::Helper::switchAccount(...);// When switching user is selected    
             break;    
           default:    
    // other exception situations    
             break;    
          }    
});

API Reference: AuthV4.Helper.syncAccount

import com.hive.AuthV4    
    import com.hive.ResultAPI    
    val providerType = AuthV4.ProviderType.GOOGLE    
    AuthV4.Helper.syncAccount(providerType, object : AuthV4.Helper.AuthV4HelperListener {    
         override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {    
             when (result.code) {    
                 ResultAPI.Code.Success -> {    
                     // normal    
                 }    
                 ResultAPI.Code.AuthV4ConflictPlayer -> {    
                     // account conflict    
                     // ex) When using Hive UI   
                     // AuthV4.Helper.showConflict(...);    
                     //or    
                     // ex) When implementing GameUI    
                     // AuthV4.Helper.resolverConflict(...);// When selecting the current user    
                     // AuthV4.Helper.switchAccount(...);// When selecting user switch    
                 }    
                 else -> {    
                     // other exception situations    
                 }    
             }    
         }    
})

API Reference: AuthV4.Helper.INSTANCE.syncAccount

import com.hive.AuthV4;    
    import com.hive.ResultAPI;    
    AuthV4.ProviderType providerType = AuthV4.ProviderType.GOOGLE;    
    AuthV4.Helper.INSTANCE.syncAccount(providerType, (result, playerInfo) -> {    
         switch (result.getCode()) {    
             case Success:    
                 // normal    
                 break;    
             case AuthV4ConflictPlayer:    
                 // account conflict    
                 // ex) When using Hive UI   
                 // AuthV4.Helper.INSTANCE.showConflict(...);    
                 //or    
                 // ex) When implementing GameUI    
                 // AuthV4.Helper.INSTANCE.resolverConflict(...);// When selecting the current user    
                 // AuthV4.Helper.INSTANCE.switchAccount(...);// When selecting user switch    
                 break;    
             default:    
                 // other exception situations    
                 break;    
         }    
});

API Reference: AuthV4Interface.helper().syncAccount

import HIVEService    
    let providerType: ProviderType = .Google    
    AuthV4Interface.helper().syncAccount(providerType) { result, playerInfo in    
         switch result.getCode() {    
           case .success:    
             // normal    
           case .authV4ConflictPlayer:    
             // account conflict    
             // ex) When using Hive UI   
             // AuthV4Interface.helper().showConflict(...);    
             //or    
             // ex) When implementing GameUI    
             // AuthV4Interface.helper().resolverConflict(...);// When selecting the current user    
             // AuthV4Interface.helper().switchAccount(...);// When selecting user switch    
           default:    
    // other exception situations    
             break    
         }    
}

API Reference: [ HIVEAuthV4 helper] syncAccount

#import <HIVEService/HIVEService-Swift.h>    
    HIVEProviderType providerType = HIVEProviderTypeGoogle    
    [[HIVEAuthV4 helper] syncAccount: providerType handler: ^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {    
    switch ([result getCode]) {    
    case HIVEResultAPICodeSuccess:    
    // normal    
    break;    
    case HIVEResultAPICodeAuthV4ConflictPlayer:    
              // account conflict    
             // ex) When using Hive UI   
             // [[HIVEAuthV4 helper] showConflict: ...];    
             //or    
             // ex) When implementing GameUI    
             // [[HIVEAuthV4 helper] resolverConflict:...];// When selecting the current user    
             // [[HIVEAuthV4 helper] switchAccount:...];// When selecting user switch    
    break;    
    default:    
    // other exception situations    
    break;    
    }    
}];

Guest login

Hive SDK supports Guest Login to allow users to use the game as a guest without selecting an IdP. You can implement this function for user to choose guest from the Explicit Login UI provided by Hive SDK, or from the customized UI by game. The Windows environment does not support guest sign-in.

Make sure to comply with the following policy when logging in as a guest.

Guest login policy

  • Build a game available for both guest users and Hive members equally.

    Most features of Hive platform are available for guest users. So, implement your games the same for both guest users and IdP-connected users. For example, guest users are also able to purchase items and pay in the game.

  • Do not allow guest users to sign out.

    If a user logs in as a guest and then logs out, the user can no longer sign in with the same PlayerID. Therefore, do not provide a logout button to prevent users from signing out when their state is the guest.

  • Guest Login Policy with Chinese IP.

    If users access the game with Chinese IP, only authorized members can charge game money or purchase items (started from May 1, 2017). Therefore, IdP lists available with Chinese IP do not include Guest Login.

Implement signIn() method with the parameter, ProviderType.GUEST to execute Guest Login. Followings are sample codes to execute Guest Login.

Note

PlayerID in guest state without IdP authentication does not have providerInfoData of playerInfo.

API Reference: hive.AuthV4.signIn

using hive;    
    AuthV4.signIn(AuthV4.ProviderType.GUEST, (ResultAPI result, AuthV4.PlayerInfo playerInfo) => {    
         if (result.isSuccess()) {    
             // Authentication successful    
             // playerInfo: Authenticated user information    
         }    
});
#include "HiveAuthV4.h"

FHiveAuthV4::SignIn(EHiveProviderType::GUEST,
                                        FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {

        if (Result.IsSuccess()) {
                // Authentication successful    
      // playerInfo: Authenticated user information 
        }
}));

API Reference: Auth4::signIn

#include <HIVE_SDK_Plugin/HIVE_CPP.h>    
    using namespace std;    
    using namespace hive;    
    AuthV4::signIn(ProviderType::GUEST, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {    
        if (result.isSuccess()) {    
        // Authentication successful    
        // playerInfo: Authenticated user information    
        }    
});

API Reference: AuthV4.signIn

import com.hive.AuthV4    
    import com.hive.ResultAPI    
    AuthV4.signIn(AuthV4.ProviderType.GUEST, object : AuthV4.AuthV4SignInListener {    
         override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {    
             if (result.isSuccess) {    
                 // Authentication successful    
                 // playerInfo: Authenticated user information    
             }    
         }    
})

API Reference: com.hive.Auth4.signIn

import com.hive.AuthV4;    
    import com.hive.ResultAPI;    
    AuthV4.INSTANCE.signIn(AuthV4.ProviderType.GUEST, (result, playerInfo) -> {    
         if (result.isSuccess()) {    
             // Authentication successful    
             // playerInfo: Authenticated user information    
         }    
});

API Reference: AuthV4Interface.signIn

import HIVEService    
    AuthV4Interface.signIn(.Guest) { result, playerInfo in    
        if result.isSuccess() {    
        // Authentication successful    
        // playerInfo: Authenticated user information    
        }    
}

API Reference: HIVEAuth4:signIn

#import <HIVEService/HIVEService-Swift.h>    
    [HIVEAuthV4 signIn: HIVEProviderTypeGuest handler: ^(ResultAPI *result, HIVEPlayerInfo *playerInfo) {    
        if ([result isSuccess]) {    
        // Authentication successful    
        // playerInfo: Authenticated user information    
        }    
}];

Custom login

Custom Login is a feature of implementing login with an external IdP that Hive SDK does not support. Follow the Auth V4 Custom Authentication guide to create an authKey that uses for calling the Custom Login API. You can confirm the user's information who signed in with custom login by accessing customProviderInfoData with the PlayerInfo object which is passed as a callback of the Custom Login API. ProviderType(enum) of customProviderInfoData are all set as CUSTOM, and can be identified in detail with ProviderName(String).

  • The information of IdP that implemented custom login in-game is not include as a result of calling setup() and showSignIn() method of AuthV4 class.
  • If you get the playerId and playerToken after first executing custom login, the Result API of authV4SessionExist(code) will be passed as a callback when you re-call the custom login API. In this case, implement signIn() method with the parameter, ProviderType.Auto to execute automatic login with a previous login account.
  • The connect() and disconnect() method of AuthV4 class currently do not support additional connection and disconnection of a custom login IdP.
  • The additional sync or disconnection of IdPs for custom login are supported with the connectWithAuthKey() and disconnectWithName() methods.

Followings are sample codes to implement the custom login.

API Reference: hive.AuthV4.signIn

// Twitter login implemented directly in the game    
    Game.Login("CUSTOM_TWITTER", (string authKey) => {    
    AuthV4.signInWithAuthKey(authKey, (ResultAPI result, PlayerInfo playerInfo) => {    
        if (result. isSuccess()) {    
            Dictionary<string, ProviderInfo> customProviderInfoData = playerInfo.customProviderInfoData;    
            ProviderInfo providerInfo = customProviderInfoData["CUSTOM_TWITTER"];    
            // Check the following user linkage information    
            providerInfo. providerType; // ProviderType.CUSTOM, customs have a fixed type, so you need to distinguish them by providerName    
            providerInfo. providerName; // "CUSTOM_TWITTER"    
            providerInfo. providerUserId; // user id used for self-implemented twitter login    
            return;    
        }    
        else if (result.code == ResultAPI.Code.AuthV4SessionExist) {    
            // If you need to log in automatically after having already issued playerId and playerToken    
            // TODO: AuthV4.signIn(ProviderType.AUTO, (ResultAPI _result, PlayerInfo playerInfo) => {});    
        }    
        else if (result.code == ResultAPI.Code.AuthV4NotInitialized) {    
            // TODO: need to initialize SDK    
        }    
        else if (result.code == ResultAPI.Code.AuthV4InvalidParam) {    
            // TODO: Need to check whether the passed authKey value is NULL or empty    
        }    
        else if (result. needExit()) {    
            // TODO: implement app exit functionality    
            // Example) Application.Quit();    
        }    
    });    
});
#include "HiveAuthV4.h"

// Twitter login implemented directly in the game 
void GameLogin(const FString& AuthKey)
{
        FHiveAuthV4::SignInWithAuthKey(AuthKey, FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {

                if (Result.IsSuccess()) {
                        TMap<FString, FHiveProviderInfo> CustomProviderInfoData = PlayerInfo.CustomProviderInfoData;
                        if (const FHiveProviderInfo* ProviderInfo = CustomProviderInfoData.Find(TEXT("CUSTOM_TWITTER"))) {
                                EHiveProviderType ProviderType = ProviderInfo->ProviderType;// EHiveProviderType::CUSTOM, ProviderType::CUSTOM, customs have a fixed type, so you need to distinguish them by providerName    
                                FString ProviderName = ProviderInfo->ProviderName;  // "CUSTOM_TWITTER" 
                                FString ProviderUserId = ProviderInfo->ProviderUserId; // user id used for self-implemented twitter login
                        }
                } else if (Result.NeedExit()) {
                        // 예) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
                } else if (Result.Code == FHiveResultAPI::ECode::AuthV4SessionExist) {
                        // If you need to log in automatically after having already issued playerId and playerToken    
            // TODO: AuthV4.signIn(ProviderType::AUTO, [=](ResultAPI const & _result, PlayerInfo const & playerInfo) {});
                } else if (Result.Code == FHiveResultAPI::ECode::AuthV4NotInitialized) {
                        // TODO: need to initialize SDK 
                } else if (Result.Code == FHiveResultAPI::ECode::AuthV4InvalidParam) {
                        // TODO: Need to check whether the passed authKey value is NULL or empty
                }
        }));
}

API Reference: Auth4::signIn

using namespace std;    
    using namespace hive;    
    // Twitter login implemented directly in the game    
    Game::Login("CUSTOM_TWITTER", [=](string authKey) {    
    AuthV4::signInWithAuthKey(authKey, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {    
        if (result. isSuccess()) {    
            map<string, ProviderInfo> customProviderInfoData = playerInfo.customProviderInfoData;    
            ProviderInfo providerInfo = customProviderInfoData["CUSTOM_TWITTER"];    
            // Check the following user linkage information    
            providerInfo. providerType; // ProviderType::CUSTOM, customs have a fixed type, so you need to distinguish them by providerName    
            providerInfo. providerName; // "CUSTOM_TWITTER"    
            providerInfo. providerUserId; // user id used for self-implemented twitter login    
            return;    
        }    
        else if (result.code == ResultAPI::Code::AuthV4SessionExist) {    
            // If you need to log in automatically after having already issued playerId and playerToken    
            // TODO: AuthV4.signIn(ProviderType::AUTO, [=](ResultAPI const & _result, PlayerInfo const & playerInfo) {});    
        }    
        else if (result.code == ResultAPI::Code::AuthV4NotInitialized) {    
            // TODO: need to initialize SDK    
        }    
        else if (result.code == ResultAPI::Code::AuthV4InvalidParam) {    
            // TODO: Need to check whether the passed authKey value is NULL or empty    
        }    
        else if (result. needExit()) {    
            // TODO: implement app exit functionality    
            // Users of the Cocos2d-x engine    
            // ex) exit(0);    
            // Unreal engine users    
            // Example) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);    
        }    
    });    
});

API Reference: com.hive.Auth4.signIn

// Twitter login implemented directly in the game
    Game.Login("CUSTOM_TWITTER") { authKey: String ->
    AuthV4.signInWithAuthKey(authKey, object : AuthV4.AuthV4SignInListener {
            override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {

                    if (result.isSuccess && playerInfo != null) {
                            playerInfo.customProviderInfoData["CUSTOM_TWITTER"]?.let { providerInfo ->
                                    providerInfo.providerType // ProviderType.CUSTOM, since custom types are fixed, it is necessary to distinguish them by providerName
                                    providerInfo.providerName // "CUSTOM_TWITTER"
                                    providerInfo.providerUserId // user id used for Twitter login
                            }
                    }
                    else if (result. needExit()) {
                            // TODO: implement app exit functionality
                            // ex) exitProcess(0)
                    }
                    else if (result.code == ResultAPI.Code.AuthV4SessionExist) {
                            // If you need to log in automatically after having already issued playerId and playerToken
                            // TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener)
                    }
                    else if (result.code == ResultAPI.Code.AuthV4NotInitialized) {
                            // TODO: need to initialize SDK
                    }
                    else if (result.code == ResultAPI.Code.AuthV4InvalidParam) {
                            // TODO: Need to check whether the passed authKey value is NULL or empty
                    }
            }
    })
    }

API Reference: com.hive.Auth4.signIn

// Twitter login implemented directly in the game
    Game.Login("CUSTOM_TWITTER") { authKey: String ->
    AuthV4.INSTANCE.signInWithAuthKey(authKey, new AuthV4.AuthV4SignInListener() {
            @Override
            public void onAuthV4SignIn(@NonNull ResultAPI result, @Nullable AuthV4.PlayerInfo playerInfo) {

                    if(result.isSuccess() && playerInfo != null) {
                            HashMap<String, AuthV4.ProviderInfo> customProviderInfoData = playerInfo.getCustomProviderInfoData();
                            AuthV4.ProviderInfo providerInfo = customProviderInfoData.get("CUSTOM_TWITTER");
                            // Check the following user linkage information
                            if (providerInfo != null){
                                    providerInfo.getProviderType(); // AuthV4.ProviderType.CUSTOM, since custom types are fixed, it is necessary to differentiate by providerName
                                    providerInfo.getProviderName(); // "CUSTOM_TWITTER"
                                    providerInfo.getProviderUserId(); // user id used for self-implemented twitter login
                            }
                    } else if (result. needExit()) {
                            // TODO: implement app exit functionality
                            // ex) System.exit(0);
                    } else if (result.getCode() == ResultAPI.Code.AuthV4SessionExist) {
                            // If you need to log in automatically after having already issued playerId and playerToken
                            // TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener)
                    } else if (result.getCode() == ResultAPI.Code.AuthV4NotInitialized) {
                            // TODO: need to initialize SDK
                    } else if (result.getCode() == ResultAPI.Code.AuthV4InvalidParam) {
                            // TODO: Need to check whether the passed authKey value is NULL or empty
                    }
            }
    });
    }

API Reference: HIVEAuth4:signIn

swift // Twitter login implemented directly in the game Game.login("CUSTOM_TWITTER") { (authKey) in AuthV4Interface.signInWithAuthKey(authKey) { (result, playerInfo) in if result. isSuccess() { let customProviderInfoData = playerInfo?.customProviderInfoData; let providerInfo = customProviderInfoData?["CUSTOM_TWITTER"] // Check the following user linkage information providerInfo?.providerType; // AuthProviderType, since custom types are fixed, it is necessary to distinguish them by providerName providerInfo?.providerName; // "CUSTOM_TWITTER" providerInfo?.providerUserId; // user id used for self-implemented twitter login return } else if result.getCode() == .authV4SessionExist { // If you need to log in automatically after having already issued playerId and playerToken // TODO: AuthV4Interface.signIn(.auto) { (result, playerInfo) in } } else if result.getCode() == .authV4NotInitialized { // TODO: need to initialize SDK } else if result.getCode() == .authV4invalidParam { // TODO: Need to check whether the passed authKey value is nil or empty } else if result. needExit() { // TODO: Implement app shutdown functionality. // ex) exit(0) } } }

API Reference: HIVEAuth4:signIn

// Twitter login implemented directly in the game
    [Game login:@"CUSTOM_TWITTER" handler:^(NSString* authKey) {
    [HIVEAuthV4 signInWithAuthKey:authKey handler:^(HIVEResultAPI* result, HIVEPlayerInfo* playerInfo) {
                    if (result. isSuccess) {
                            NSDictionary<NSString*, HIVEProviderInfo*>* customProviderInfoData = playerInfo.customProviderInfoData;
                            ProviderInfo* providerInfo = [customProviderInfoData objectForKey:@"CUSTOM_TWITTER"];
                            // Check the following user linkage information
                            providerInfo. providerType; // HIVEProviderTypeCustom, customs have a fixed type, so you need to distinguish them by providerName
                            providerInfo. providerName; // "CUSTOM_TWITTER"
                            providerInfo. providerUserId; // user id used for self-implemented twitter login
                            return;
                    }
                    else if (result.getCode == HIVEResultAPICodeAuthV4SessionExist) {
                            // If you need to log in automatically after having already issued playerId and playerToken
                            // TODO: [HIVEAuthV4 signIn:HIVEProviderTypeAuto, handler:^(HIVEResultAPI* _result, HIVEPlayerInfo* playerInfo) {}];
                    }
                    else if (result.getCode == HIVEResultAPICodeAuthV4NotInitialized) {
                            // TODO: need to initialize SDK
                    }
                    else if (result.getCode == HIVEResultAPICodeAuthV4InvalidParam) {
                            // TODO: Need to check whether the passed authKey value is NULL or empty
                    }
                    else if (result. needExit) {
                            // TODO: Implement app shutdown functionality.
                            // ex) exit(0);
                    }
    }];
    }];

Username

Due to issues such as the US COPPA, when accessing from the United States or its territories and logging in with an IdP, you must enter your username to enable authentication for additional user identification. For reference, the countries included in the US territory are American Samoa (AS), Guam (GU), Northern Mariana Islands (MP), Puerto Rico (PR), US Minor Archipelago (UM), and US Virgin Islands (VI). The username input screen for user identification is as follows.

  • The username input screen is used only for user identification, so it is exposed only once when first linking with the IdP and is not exposed other than that.
  • When logging in as a guest, the username input screen is not displayed.

Verifying authentication token key

Game server can validate the authentication token key by using the returned token, playerId, and DID information after successful login. Authentication allows multi-device logins and duplicate connections.

Unless your game allows duplicate access with one ID, game server exposes a notice on the logged-in device and terminates the game. Then, the secondly logged-in device keeps its login state for game play. If user keeps duplicate connections without terminating the game from one device, the game play may not be recorded concisely. Therefore, make sure to manage the token key that has been verified or implement the function by managing the session key of the game itself using the token key to process this function.

Implement the function by referring to Hive Server API > Verifying Authentication v4 Token.

Obtaining TalkPlus login token

To log in to TalkPlus, you need the login token obtained by calling AuthV4.getHiveTalkPlusLoginToken API after login (signIn()) via Auth v4 interface. (See TalkPlus Login Guide)

AuthV4.getHiveTalkPlusLoginToken((ResultAPI result, String loginToken) => {
    if (result.isSuccess()) {
        // SUCCESS
        // TODO: Check the loginToken you received and execute TalkPlus login
    }
});
// Kotlin
AuthV4.getHiveTalkPlusLoginToken(object : AuthV4.AuthV4GetHiveTalkPlusLoginTokenListener {
    override fun onAuthV4GetHiveTalkPlusLoginToken(resultApi: ResultAPI, loginToken: String?) {
        if (resultApi.isSuccess) {
            // SUCCESS
        }
    }
}
// Java
com.hive.AuthV4.INSTANCE.getHiveTalkPlusLoginToken(new com.hive.AuthV4.AuthV4GetHiveTalkPlusLoginTokenListener() {
    @Override
    public void onAuthV4GetHiveTalkPlusLoginToken(@NotNull ResultAPI result, @Nullable String loginToken) {
if (result.isSuccess()) {
// SUCCESS
}
    }
});
// Swift
AuthV4Interface.getHiveTalkPlusLoginToken { result, loginToken in
    if (result.isSuccess()) {
        // SUCCESS
    }
}
// Objective-c
[HIVEAuthV4 getHiveTalkplusLoginToken:^(HIVEResultAPI* result, NSString* loginToken) {
    if ([result isSuccess]) {
        // SUCCESS
    }
}];

Detecting changes in IdP account in the background

Users can change their Apple Game Center or Google Play game accounts through device settings while playing the game. If you need to check whether the IdP account is matched with the account connected with the current PlayerID, implement setProviderChangedListener() after initializing Hive SDK. If you implement the API, user can receive an event which notifies the changes in IdP account linked on the user device when game resumes.

iOS works when the account in Apple Game Center is changed, and Android works when the account in Google Play Games is changed. And The response will be delivered only if the currently logged in PlayerID is connected with the relevant IdP. If you receive the change event in IdP account, configure the UI which allows the user to choose whether to use the IdP account logged in on the device. If the user selects the IdP account logged in on the device, call signOut to sign out and proceed with Implicit Login.

Warning

Due to a Google Play Games working issue, devices with Google Play Games released after July 2021 cannot change IdP accounts in the background.

Note

This function may stop the play and request to change the user account, so use it only when account sync is required; the access to the lobby or to the shop.

Followings are sample codes to receive events that IdP account setting on device is changed when the player resumes the game.

API Reference: hive.AuthV4.setProviderChangedListener

using hive;

AuthV4.setProviderChangedListener((ResultAPI result, AuthV4.ProviderInfo providerInfo) => {
if (!result.isSuccess()) {
return;
}

    if (providerInfo != null && providerInfo.providerType == AuthV4.ProviderType.APPLE) {
        // Change GameCenter user information
    }
});
#include "HiveAuthV4.h"

FHiveAuthV4::SetProviderChangedListener(FHiveAuthV4OnCheckProviderDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHiveProviderInfo& ProviderInfo) {
        if (Result.IsSuccess()) {
                // Call success. Check the changed user information through the ProviderInfo object.
        }
}));

API Reference: AuthV4::setProviderChangedListener

#include <HIVE_SDK_Plugin/HIVE_CPP.h>
using namespace std;
using namespace hive;

AuthV4::setProviderChangedListener([=](ResultAPI const & result, ProviderInfo const & providerInfo) {
    if (!result.isSuccess()) {
    return;
    }

    if (providerInfo != null && providerInfo.providerType == ProviderType::GOOGLE) {
    // Change Google Play Game Service account
    }
});

API Reference: AuthV4.setProviderChangedListener

import com.hive.AuthV4
import com.hive.ResultAPI

AuthV4.setProviderChangedListener(object : AuthV4.AuthV4CheckProviderListener {
    override fun onDeviceProviderInfo(result: ResultAPI, providerInfo: AuthV4.ProviderInfo?) {
        if (!result.isSuccess) {
            return
        }

        if (providerInfo != null && providerInfo.providerType == AuthV4.ProviderType.GOOGLE) {
            // Change Google Play Game Service account
        }
    }
})

API reference : : com.hive.authv4.SetproviderChangeDlistener

import com.hive.AuthV4;
import com.hive.ResultAPI;

AuthV4.INSTANCE.setProviderChangedListener((result, providerInfo) -> {
    if (!result.isSuccess()) {
        return;
    }

    if (providerInfo != null && providerInfo.getProviderType() == AuthV4.ProviderType.GOOGLE) {
        // Change Google Play Game Service account
    }
});

API Reference: AuthV4Interface .setProviderChangedListener

import HIVEService

AuthV4Interface.setProviderChangedListener() { result, providerInfo in
    if !result.isSuccess() {
    return
    }

    if let providerInfo = providerInfo, providerInfo.providerType == .Apple {
    // Change GameCenter user information
    }
}

API Reference: HIVEAuthV4:setProviderChangedListener

#import <HIVEService/HIVEService-Swift.h>

[HIVEAuthV4 setProviderChangedListener: ^(HIVEResultAPI *result, ProviderInfo *providerInfo) {
if (![result isSuccess]) {
return;
}
    if (providerInfo != nil && providerInfo.providerType == HIVEProviderTypeApple) {
    // Change GameCenter user information
    }
}];

Initializing game data

Make sure not to implement logout when initializing game data. PlayerID is not deleted through the initialization, therefore, crash among accounts may occur. Let user play the game with the currently signed-in account, and do not implement the logout function before user clearly request by tapping the logout button.

Logout

Warning
  • When logging out, the PlayerId (authentication information), PlayerToken (session information), and all IDP session information are deleted.
  • When logging out, the values set with the setter APIs (set API series) are not initialized or deleted.
    • Every setter methods in Configuration, Auth, Auth v4, Promotion, and Push class
    • Examples: Configuration.setServer, Configuration.setUseLog, Configuration.setGameLanguage, Configuration.setHiveCertificationKey, Auth.setEmergencyMode, AuthV4.setProviderChangedListener, Promotion.setUserEngagementReady, Promotion.setAddtionalInfo, Push.setRemotePush, Push.setForegroundPush, etc.
    • Starting from Hive SDK v4 24.3.0, an error code will be returned when a guest user logs out. The client and server sessions will be maintained thereafter.
  • The effective range of the value set by the setter method is maintained within the life cycle of the app, not in the login or logout state.

If login is performed, PlayerID and authentication token key are already issued. Logout is responsible for initializing the PlayerID and the token key. If logout is completed by implementing signOut(), move to the game title and execute the Explicit Login when user taps the title.

Note
  • Implement not to provide a logout function when user state is guest because the same PlayerID is unable to find after guest logs out.
  • Even when user signs out, the connection status of IdP with PlayerID does not change.
  • Go to the game title when user signed out. When the player taps the title, execute Explicit Login.
  • If user restarts the game app after signing out, Implicit Login should be executed.

Followings are sample codes to implement sign-out.

API Reference: hive.AuthV4.signOut

using hive;    

    AuthV4.Helper.signOut (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {    
         switch(result.code) {    
             case ResultAPI.Code.Success:    
                 // Logout successful    
                 break;    
             default:    
                 // other exception situations    
                 break;    
         }    
});
#include "HiveAuthV4.h"

FHiveAuthV4::Helper::SignOut(FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TOptional<FHivePlayerInfo>& PlayerInfo) {
        AHIVESDKV4TesterGameMode::getGameModeInstance()->appendLogString(ELogType::AuthV4Helper ,TEXT("Helper::SignOut Result = %s"), *(Result.ToString()));
        switch (Result.Code) {
                case FHiveResultAPI::ECode::Success:
                        // Logout successful
                        break;
                default:
                        // other exception situations
                        break;
        }
}));

API Reference: AuthV4::signOut

#include <HIVE_SDK_Plugin/HIVE_CPP.h>    
    using namespace std;    
    using namespace hive;    

    AuthV4::Helper::signOut([=](ResultAPI const & result, shared_ptr playerInfo) {    
         switch (result.code) {    
             case ResultAPI::Success:    
                 // Logout successful    
                 break;    
             default:    
                 // other exception situations    
                 break;    
         }    
});

API Reference: AuthV4.Helper.signOut

import com.hive.AuthV4
import com.hive.ResultAPI

AuthV4.Helper.signOut(object : AuthV4.Helper.AuthV4HelperListener {
    override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        when (result.code) {
            ResultAPI.Code.Success -> {
                // Logout successful
            }
            else -> {
                // other exception situations
            }
        }
    }
})

API Reference: AuthV4.Helper.INSTANCE.signOut

import com.hive.AuthV4;
import com.hive.ResultAPI;

AuthV4.Helper.INSTANCE.signOut((result, playerInfo) -> {
    switch (result.getCode()) {
        case Success:
            // Logout successful
            break;
        default:
            // other exception situations
            break;
    }
});

API Reference: AuthV4Interface.helper().signOut()

import HIVEService

AuthV4Interface.helper().signOut() { result, playerInfo in
    switch result.getCode() {
        case .success:
            // Logout successful
        default:
            // other exception situations
            break
    }}

API Reference: [HIVEAuthV4 helper] signOut

#import <HIVEService/HIVEService-Swift.h>

[[HIVEAuthV4 helper] signOut: ^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
    switch ([result getCode]) {
        case HIVEResultAPICodeSuccess:
            // log-in succeed
            break;
        default:
            // other exception situations
            break;
    }
}];

Notification phrases for Game center sign-in disabled

Language Phrase
Korean Apple Game Center 로그인이 취소되었습니다.
Game Center 계정과 연동하려면 [설정 >; Game Center]에서 로그인한 후 다시 시도해주세요.
English Your login to the Game Center has been canceled.
Log in at [Settings >; Game Center] to sync to the Game Center Account and try again.
Japanese Apple Game Center ログインがキャンセルされました。
Game Center アカウントと連動するには [設定 >; Game Center] にログインした後、再度お試しください。
Chinese (Simplified) Apple Game Center已退出登录。
若想与Game Center账号同步,请在设备[设置 >; Game Center]中重新登录后再试。
Chinese (Traditional) 登入Apple Game Center已取消。
若想連動Game Center帳號,請至[設定 >; Game Center]登入後,再試一次。
French Ta connexion au Game Center a été annulée.
Connecte-toi dans [Réglages >; Game Center] pour synchroniser ton compte Game Center et essaie de nouveau.
German Das Einloggen ins Apple Game Center wurde abgebrochen.
Die Synchronisation mit dem Game Center-Konto läuft über [Einstellungen >; Game Center]. Logge dich ein und versuche es erneut.
Russian Ваш авторизация в Game Center была отменена.
Авторизуйтесь в Game Center через [Настройки >; Game Center] и повторите попытку.
Spanish Tu Inicio de Sesión en Game Center ha sido cancelado.
Inicia Sesión en [Configuración >; Game Center] para sincronizar a la Cuenta de Game Center, e inténtalo de nuevo.
Portuguese O seu login no Game Center foi cancelado.
Faça o login em [Configurações >; Game Center] para sincronizar com a Conta do Game Center e tente novamente.
Indonesian Login ke Apple Game Center telah dibatalkan.
Hubungkan akun Game Center dengan login di [Pengaturan >; Game Center] dan coba lagi.
Malay Log masuk ke Game Center anda telah dibatalkan.
Log masuk di [Tetapan >; Game Center] untuk disegerakkan ke Akaun Game Center dan cuba lagi.
Vietnamese Đã hủy bỏ đăng nhập vào Apple Game Center.
Đăng nhập tại [Cài đặt >; Game Center] để đồng bộ với tài khoản Game Center và thử lại.
Thai การล็อกอินเข้า Game Center ของคุณถูกยกเลิก
ล็อกอินที่ [การตั้งค่า >; Game Center] เพื่อเชื่อมต่อบัญชี Game Center และโปรดลองอีกครั้ง
Italian L'accesso all'Apple Game Center è stato annullato.
Fai log-in su [Impostazioni >; Game Center] per sincronizzare il tuo account con il Game Center e riprova.
Turkish Apple Oyun Merkezine girişiniz iptal edilmiştir.
Oyun Merkezi Hesabına ulaşmak için [Ayarlar >; Oyun Merkezi]'nden giriş yapın ve tekrar deneyin.
Arabic تم إلغاء تسجيل الدخول إلى مركز الألعاب.
سجل الدخول إلى [الإعدادات >; مركز الألعاب] للمزامنة مع حساب مركز الألعاب وحاول مرة أخرى.