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.
- Automatic Login and Implicit Login
- Explicit Login
- Checking Logged-in IdP Account on Device
- 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
-
Implicit Login is unavailable for Google Build if the target of your game is children under the age of 13, because Google Play Games Services can not be applied. For more information, see Quality Checklist for Google Play Games Services.
-
Make sure to process Implicit Login by Google Play Games only when user signs in your game for the first time. For more information, see 1.5 Remember if players declined signing-in in Google developer guide.
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:
-
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
andplayerToken
were issued.
From the perspective of the app developers, there must have been at least one successful execution ofAuthV4.Helper.signIn
,AuthV4.showSignIn
, orAuthV4.signInWithAuthKey
in an online state, with the reception ofplayerId
andplayerToken
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. -
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¶
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
- You must create a login button by referring to the design guide provided by each IdP when creating a login button.
- Game Center: No additional guidelines
- Google Play Games: Branding Guidelines
- Google: Branding Guidelines
- Hive membership: Hive BI Guidelines
- Facebook: Brand Resource Center
- QQ: Policies and Regulations
- WeChat: Primary brand & Guidelines
- VK: VK Brandbook
- Apple: Human Interface Guidelines
- LINE: LINE Login Button Design Guidelines
- Huawei: HUAWEI ID Icon Specifications
- You must comply with Google sign-in button guide to get your game featured on Google Play Store.
- For multilanguage login button name applied in auth, click here.
- 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.
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
API Reference: Auth4::signIn
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
API Reference: AuthV4Interface.signIn
API Reference: HIVEAuth4:signIn
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()
andshowSignIn()
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, implementsignIn()
method with the parameter,ProviderType.Auto
to execute automatic login with a previous login account.- The
connect()
anddisconnect()
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()
anddisconnectWithName()
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)
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
#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
API Reference: AuthV4Interface .setProviderChangedListener
API Reference: HIVEAuthV4:setProviderChangedListener
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
#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
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
API Reference: AuthV4Interface.helper().signOut()
API Reference: [HIVEAuthV4 helper] signOut
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 | تم إلغاء تسجيل الدخول إلى مركز الألعاب. سجل الدخول إلى [الإعدادات >; مركز الألعاب] للمزامنة مع حساب مركز الألعاب وحاول مرة أخرى. |