登录注销
登录认证包括以下步骤。
Note
- SDK 版本低于 4.7.0 不支持 Helper。请参考 [以下内容] 以获取现有的登录应用程序方法。
- 有关 AuthV4.Helper 的描述,请参考 身份验证 页面。
登录¶
身份验证中的登录包括以下步骤。
Authv4Helper 是一个执行与登录相关的一系列过程的类,并根据响应值配置为导航到适当的屏幕。
请在配置登录时参考以下内容。
Note
苹果不支持 iOS 企业构建的 Apple Game Center 和应用内购买。因此,在 iOS 企业构建中,无法使用 Apple Game Center 账户进行隐式登录,显式登录也无法利用 Apple Game Center。当为 iOS 企业构建时,控制台中的 登录类型 不能包含 Apple Game Center。
Note
- 如果游戏主要面向13岁以下的儿童,则无法使用Google Play游戏服务,并且无法在Google构建中使用隐式登录。有关更多详细信息,请参阅Google Play游戏服务质量检查清单。
- Google Play游戏的隐式登录仅应在第一次登录时尝试。有关更多详细信息,请参阅Google开发者指南1.5 记住玩家是否拒绝登录。
Note
- 在中国,无法使用Google Play游戏,因此在Android上无法使用隐式登录。
- 在中国,无法使用Facebook,因此Facebook未包含在IdP列表中。
- 由于只有经过实名验证的用户才能从中国IP充值或消费资源(自2017年5月1日起生效),因此访客登录未包含在可以从中国IP登录的IdP列表中。
Note
iOS即使在取消Apple Game Center登录时也不会显示登录屏幕。因此,指导消息可以通过SDK直接调用AuthV4Helper
类的showGameCenterLoginCancelDialog()
方法来显示,或者可以选择由游戏显示。如果您想为用户提供重新连接其Game Center帐户的消息,请在AuthV4.signIn(AuthV4.ProviderType.APPLE, ...)
和AuthV4.connect(AuthV4.ProviderType.APPLE, ...)
的回调结果为取消时使用Game Center取消指导消息。
Note
如果用户在其设备未使用 Apple ID 登录的情况下尝试使用 Apple 登录,则 AuthV4Helper 类的 connect()
、signIn()
方法 将触发 AuthV4SignInAppleUnknown 错误。Apple ID 登录指导弹窗将自动显示,因此游戏工作室无需显示单独的指导弹窗。
如果用户尝试使用 Apple 登录,但他们的设备未使用 Apple ID 登录,则在调用 AuthV4Helper 类的 connect()
、signIn()
方法的过程中会发生 AuthV4SignInAppleUnknown 错误 这里。Apple ID 登录指导弹出窗口会自动显示,因此游戏工作室无需显示单独的 弹出窗口 进行指导。
自动登录和隐式登录¶
自动登录¶
这意味着用户通过在iOS上链接他们的Apple Game Center账户和在Android上链接他们的Google Play Games账户,自动登录,而无需选择登录方式。它实现了自动登录,并在自动登录失败时执行隐式登录。
在 iOS 环境中使用自动登录,您需要添加游戏中心权限,如果您勾选了“Apple GameCenter”依赖项,Unity 会通过 Unity PostProcess 自动添加该权限。在 iOS Native 中,Xcode 会自动添加游戏中心权限。
在iOS环境中使用自动登录,您需要添加Game Center权限。在Unity中,如果您已勾选“Apple GameCenter”依赖项,它将通过Unity PostProcess自动添加权限。对于iOS Native,Xcode将自动添加Game Center权限。
离线模式¶
在 Hive SDK v4 23.1.0 及以上版本中,即使用户设备在应用启动时未连接到网络,也可以提供自动登录功能(AuthV4.signIn
使用 ProviderType.AUTO
,或 AuthV4.Helper.signIn
)。要使用离线模式,请按照以下说明进行操作。
- 您必须成功在线执行该应用程序以进行显式、隐式、访客或自定义登录,并接收到
playerId
和playerToken
。
从应用程序开发者的角度来看,必须至少在线成功执行过一次 AuthV4.Helper.signIn
、AuthV4.showSignIn
或 AuthV4.signInWithAuthKey
,并作为回调接收到 playerId
和 playerToken
。从用户的角度来看,用户必须至少在设备连接到网络时成功登录过一次应用程序。然而,如果用户的账户在他们上次尝试在线登录时被暂停或限制,则用户即使在离线模式下也无法登录。
- 在 Hive 控制台中激活离线模式 应用中心 > 项目管理 > 游戏详情 > Hive 产品设置。
Windows环境中的自动登录¶
Windows环境也支持自动登录,可以在Hive 控制台应用中心中激活或停用。然而,Windows中的自动登录与移动设备上的行为有所不同。Windows中自动登录的差异如下。
- 在移动设备上,登录状态在登录后会自动保持,但在Windows上,仅在用户激活“保持我登录”复选框(在登录UI的IdP列表底部显示)时才会保持。在其他情况下,登录状态不会保持。
- 当执行 AuthV4Helper.Connect 时,在移动设备上,如果切换到新账户,新账户也会保持自动登录状态,但在Windows上,如果切换到新账户,新账户将不会保持自动登录状态。
隐式登录¶
AuthV4.Helper.signIn
尝试使用 PlayerID 的认证令牌密钥自动登录。如果没有先前登录的认证令牌密钥,它将自动登录到 iOS 的 Apple Game Center 和 Android 的 Google Play Games。如果登录失败,它将根据响应值配置适当的登录屏幕。
Note
要使用自动登录,您必须添加 Game Center 权限。如果您已检查“Apple GameCenter”依赖项,它将通过 Unity PostProcess 自动添加相应的权限。
Note
使用AuthV4Helper类时
如果正在运行游戏的用户在PGS期间拒绝隐式登录尝试,它将记住这一点,并且将不再尝试隐式登录。即使在玩家会话保持的情况下可以进行自动登录,它也会继续记住隐式登录被拒绝的状态。此内容基于Google Play游戏服务指南。
以下是一个执行自动登录的示例代码。
API 参考: hive.AuthV4.Helper.signIn
// 尝试使用 Hive SDK 登录 (signIn)
AuthV4.Helper.signIn (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {
if (result.isSuccess()) {
// 登录成功
} else if (result.needExit()) {
// TODO: 实现应用退出功能
// 例如)Application.Quit();
} else {
switch (result.code) {
case ResultAPI.Code.AuthV4ConflictPlayer:
// 账户冲突
break;
case ResultAPI.Code.AuthV4HelperImplifiedLoginFail:
// 隐式登录失败
// 例如) AuthV4.showSignIn(...);
break;
default:
// 其他异常
break;
}
}
});
#include "HiveAuthV4.h"
// 尝试登录 (signIn) 到 Hive SDK
FHiveAuthV4::Helper::SignIn(FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TOptional<FHivePlayerInfo>& PlayerInfo) {
if (Result.IsSuccess()) {
// 登录成功
} else if (Result.NeedExit()) {
// TODO: 实现应用退出功能
// 例如 UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
} else {
switch (Result.Code) {
case FHiveResultAPI::ECode::AuthV4ConflictPlayer:
// 账户冲突
break;
case FHiveResultAPI::ECode::AuthV4HelperImplifiedLoginFail:
// 隐式登录失败
// 例如 FHiveAuthV4::ShowSigIn()
break;
default:
// 其他异常
break;
}
}
}));
API 参考: Auth4::signIn
// Attempt to sign in (signIn) with Hive SDK
AuthV4::Helper::signIn([=](ResultAPI const & result, std::shared_ptr playerInfo) {
if (result.isSuccess()) {
// 登录成功
} else if (result.needExit()) {
// TODO: 实现应用退出功能
// Cocos2d-x 引擎用户
// 例如 exit(0);
// Unreal 引擎用户
// 例如 UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
} else {
switch (result.code) {
case ResultAPI::AuthV4ConflictPlayer:
// 账户冲突
break;
case ResultAPI::AuthV4HelperImplifiedLoginFail:
// 隐式登录失败
// 例如 AuthV4.showSignIn(...);
break;
default:
break;
}
}
});
API 参考: hive.AuthV4.showSignIn
// 尝试使用 Hive SDK 登录
AuthV4.Helper.signIn(object : AuthV4.Helper.AuthV4HelperListener {
override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
if (result.isSuccess) {
// 登录成功
} else if (result.needExit()) {
// TODO: 实现应用退出功能
// 例如: exitProcess(0)
} else {
when (result.code) {
ResultAPI.Code.AuthV4ConflictPlayer -> {
// 账户冲突
}
ResultAPI.Code.AuthV4HelperImplifiedLoginFail -> {
// 隐式登录失败
// 例如) AuthV4.showSignIn(...);
}
else -> {
// 其他异常情况
}
}
}
}
})
API 参考: com.hive.AuthV4.showSignIn
// Hive SDK AuthV4 认证 UI 请求
AuthV4.showSignIn(new AuthV4.AuthV4SignInListener() {
@Override
public void onAuthV4SignIn(ResultAPI result, AuthV4.PlayerInfo playerInfo) {
if (result.isSuccess()) {
// 认证成功
// playerInfo: 认证用户信息
// 获取电子邮件信息的示例
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: 实现应用退出功能
// 例如: System.exit(0);
}
}
});
API 参考: HIVEAuthV4:signIn
var email = String()
// Hive SDK AuthV4 认证 UI 请求
AuthV4Interface.showSignIn { (result, playerInfo) in
if result.isSuccess() {
// 认证成功
// playerInfo: 认证用户信息
// 检索电子邮件信息的示例
if let playerInfo = playerInfo {
// 使用 providerEmail(当前登录的提供者)搜索 providerInfo
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: 实现应用退出功能
// 例如 exit(0)
}
}
API 参考: HIVEAuthV4:signIn
// 尝试使用 Hive SDK 登录 (signIn)
[[HIVEAuthV4 helper] signIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
if (result.isSuccess) {
// 登录成功
}
else if (result.needExit) {
// TODO: 实现应用退出功能
// ex) exit(0);
}
else {
switch (result.code) {
case kAuthV4ConflictPlayer:
// 账户冲突
break;
case kAuthV4HelperImplifiedLoginFail:
// 隐式登录失败
// ex) [HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
// // 做一些事情...
// }];
break;
default:
// 其他异常
break;
}
}
}];
隐式登录行为:移动¶
在移动设备上隐式登录(例如 Hive SDK Unity Android 针对 Android/iOS 平台)(AuthV4.Helper.signIn
) 在登录不同账户时,如果与上次登录的账户发生冲突,会提示用户一个对话框,询问是否使用上次登录的账户进行登录。
隐式登录行为:PC¶
在PC上隐式登录(如Hive SDK Unity Windows等Windows平台)(AuthV4.Helper.signIn
) 在第一次登录后使用不同账户登录时,会自动使用上次登录的账户进行登录。不会发生账户冲突。
显式登录¶
显式登录是指用户选择身份提供者(IdP)进行身份验证的过程。如果自动登录和隐式登录都失败,则在用户移动到游戏标题屏幕后点击标题时实施显式登录。
显式登录用户界面可以使用Hive SDK提供的用户界面,也可以使用Hive SDK初始化完成后返回的IdP列表进行自定义。如果您正在自定义用户界面,请参考显式登录自定义部分。
IdP列表由Hive平台根据各国的政策进行控制和提供。例如,在中国,不提供Google Play游戏和Facebook,以及访客。
明确登录截图¶
使用SDK提供的UI进行实现时¶
要使用SDK提供的UI实现显式登录,您只需调用showSignIn()
方法以调用IdP列表UI。
Note
如果用户通过按“X”按钮关闭SDK提供的IdP选择UI,则必须提供再次登录的方式。用户仍然未登录。
Note
要自定义显式登录,请参考以下内容。
API 参考: hive.AuthV4.showSignIn
// Hive SDK AuthV4 认证 UI 请求
AuthV4.showSignIn((ResultAPI result, AuthV4.PlayerInfo playerInfo)=>{
if (result.isSuccess()) {
// 认证成功
// playerInfo : 认证用户信息
// 获取电子邮件信息的示例
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: 实现应用退出功能
// e.g.) Application.Quit();
}
});
#include "HiveAuthV4.h"
// Hive SDK AuthV4 认证 UI 请求
FHiveAuthV4::ShowSignIn(FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {
if (Result.IsSuccess()) {
// 认证成功 (PlayerInfo: 认证用户信息)
// 获取电子邮件信息的示例
for (const auto& ProviderInfoEntry : PlayerInfo.ProviderInfoData) {
FHiveProviderInfo ProviderInfo = ProviderInfoEntry.Value;
FString Email = ProviderInfo.ProviderEmail;
}
} else if (Result.NeedExit()) {
// TODO: 实现应用程序退出功能
// 示例) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
}
}));
API 参考: AuthV4::showSignIn
// Hive SDK AuthV4 authentication UI request
AuthV4::showSignIn([=](ResultAPI const & result, PlayerInfo const & playerInfo) {
if (result.isSuccess()) {
// Authentication successful
// playerInfo: Authenticated user 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: 实现应用程序退出功能
// 对于 Cocos2d-x 引擎用户
// 示例) exit(0);
// 对于 Unreal 引擎用户
// 示例) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
}
});
API 参考: com.hive.AuthV4.showSignIn
// Hive SDK AuthV4 认证 UI 请求
AuthV4.showSignIn(object : AuthV4.AuthV4SignInListener {
override fun onAuthV4SignIn(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
if (result.isSuccess) {
// 认证成功
// playerInfo: 认证用户信息
// 获取电子邮件信息的示例
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: 实现应用退出功能
// 例如)exitProcess(0)
}
}
})
API 参考: com.hive.AuthV4.showSignIn
// Hive SDK AuthV4 authentication UI request
AuthV4.showSignIn(new AuthV4.AuthV4SignInListener() {
@Override
public void onAuthV4SignIn(ResultAPI result, AuthV4.PlayerInfo playerInfo) {
if (result.isSuccess()) {
// 认证成功
// playerInfo: 认证用户信息
// 获取电子邮件信息的示例
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: 实现应用退出功能
// 示例) System.exit(0);
}
}
});
API 参考: HIVEAuthV4:showSignIn
var email = String()
// Hive SDK AuthV4 认证 UI 请求
AuthV4Interface.showSignIn { (result, playerInfo) in
if result.isSuccess() {
// 认证成功
// playerInfo: 认证用户信息
// 获取电子邮件信息的示例
if let playerInfo = playerInfo {
// 使用 providerEmail(当前登录的提供者)搜索 providerInfo
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: 实现应用退出功能
// 示例) exit(0)
}
}
API 参考: HIVEAuthV4:showSignIn
__block NSString* email = @"";
// Hive SDK AuthV4 认证 UI 请求
[HIVEAuthV4 showSignIn:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
if([result isSuccess]){
// 认证成功
// playerInfo: 经过认证的用户信息
// 获取电子邮件信息的示例
if(playerInfo != nil) {
// 使用 providerEmail(当前登录的提供者)搜索 providerInfo
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: 实现应用程序退出功能
// 例如 exit(0);
}
}];
明确的登录自定义¶
可自定义的显式登录用户界面可以使用 providerTypeList
实现。providerTypeList
是在调用 AuthV4.setup()
方法以初始化 Hive SDK 时返回的响应回调处理程序,或者在初始化后调用 AuthV4.Helper.getIDPList()
方法时返回的。此功能用于当您希望根据游戏用户界面显示登录屏幕或主要暴露与特定身份提供者的集成时。在实现可自定义的用户界面后,根据用户的操作使用所需的 ProviderType 调用 signIn()
方法以实现登录。
Note
- 制作登录按钮时,应参考各个 IdP 提供的设计指南来制作登录按钮。
- Game Center: 无特别规定
- Google Play Games: 品牌指南
- Google: 品牌指南
- Hive 会员资格: Hive BI 指南
- Facebook: 品牌资源中心
- QQ: 政策和规定
- WeChat: 主要品牌及指南
- VK: VK 品牌手册
- Apple: 人机界面指南
- LINE: LINE 登录按钮设计指南
- Huawei: HUAWEI ID 图标规范
- Steam: Steam 品牌指南
- X: X 品牌工具包
- Google Featured 中遵循 Google Sign-in 按钮指南非常重要。
- 应用在 Hive 认证中的多语言登录按钮名称请参考 这里。
- UI 示例截图,仅显示登录屏幕上的 Facebook 集成按钮
以下是一个示例源代码,假设用户在自定义的显式登录 UI 中选择 Google 登录。
API 参考: hive.AuthV4.signIn
using hive;
AuthV4.signIn(AuthV4.ProviderType.GOOGLE, (ResultAPI result, AuthV4.PlayerInfo playerInfo) => {
if (result.isSuccess()) {
// 调用成功
// playerInfo : 经过身份验证的用户信息。
// 获取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()) {
// 调用成功 (PlayerInfo: 经过身份验证的用户信息)
// 示例:检索 EHiveProviderType::GOOGLE 的电子邮件信息
TMap<EHiveProviderType, FHiveProviderInfo> ProviderInfoData = PlayerInfo.ProviderInfoData;
if (const FHiveProviderInfo* ProviderInfo = ProviderInfoData.Find(EHiveProviderType::GOOGLE)) {
FString Email = ProviderInfo->ProviderEmail;
}
}
}));
API 参考: Auth4::signIn
#include <HIVE_SDK_Plugin/HIVE_CPP.h>
AuthV4::signIn(ProviderType::GOOGLE, [=](ResultAPI const & result, PlayerInfo const & playerInfo) {
if (result.isSuccess()) {
// 调用成功
// playerInfo : 认证用户信息。
// 获取 ProviderType::GOOGLE 的电子邮件信息示例
map<ProviderType, ProviderInfo> providerInfoData = playerInfo.providerInfoData;
ProviderInfo providerInfo = providerInfoData[ProviderType::GOOGLE];
string email = providerInfo.providerEmail;
}
});
API 参考: 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) {
// 调用成功
// playerInfo: 认证用户信息
// 获取ProviderType.GOOGLE的电子邮件信息的示例
if (playerInfo != null) {
val providerInfoData = playerInfo.providerInfoData
val providerInfo = providerInfoData[AuthV4.ProviderType.GOOGLE]
if (providerInfo != null) {
val email = providerInfo.providerEmail
}
}
}
}
})
API 参考: com.hive.Auth4.signIn
import com.hive.AuthV4;
import com.hive.ResultAPI;
AuthV4.INSTANCE.signIn(AuthV4.ProviderType.GOOGLE, (result, playerInfo) -> {
if (result.isSuccess()) {
// 调用成功
// playerInfo: 认证用户信息
// 获取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 参考: AuthV4Interface.signIn
API Reference: HIVEAuth4:signIn
#import <HIVEService/HIVEService-Swift.h>
[HIVEAuthV4 signIn:HIVEProviderTypeGoogle handler:^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
if ([result isSuccess]){
// 调用成功
// playerInfo: 认证用户信息。
// 获取HIVEProviderTypeGoogle的电子邮件信息示例
if(playerInfo != nil) {
HIVEProviderInfo *providerInfo = playerInfo.providerInfoData[@"GOOGLE"];
if(providerInfo != nil){
NSString *email = providerInfo.providerEmail;
}
}
}
}];
检查设备上登录的 IdP 账户¶
自动登录仅使用保存的 PlayerID 的身份验证令牌密钥,而显式登录则登录到与多个 IdP 关联的账户。在这两种情况下,登录的 PlayerID 的 IdP 账户可能与实际设备 (DevicePlayer) 上登录的 IdP 账户不同。将提供指导,以统一这两个账户,为未来的成就或排行榜使用做好准备。
这是一个检查 IdP 信息的示例代码。
API 参考: 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:
// 正常
break;
case ResultAPI.Code.AuthV4ConflictPlayer:
// 账户冲突
// 例如) 使用 Hive UI 时
// AuthV4.Helper.showConflict(...);
// 或者
// 例如) 实现 GameUI 时
// AuthV4.Helper.resolverConflict(...);// 选择当前用户时
// AuthV4.Helper.switchAccount(...);// 选择用户切换时
break;
default:
// 其他异常
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:
// 正常响应
break;
case FHiveResultAPI::ECode::AuthV4ConflictPlayer:
// 账户冲突
// 例如) 使用 Hive UI 时
// FHiveAuthV4::Helper::ShowConflict()
// 例如) 实现游戏 UI 时
// FHiveAuthV4::Helper::ResolveConflict() // 当前用户选择
// FHiveAuthV4::Helper::SwitchAccount() // 用户切换选择
break;
default:
// 其他异常情况
break;
}
}))
API 参考: 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:
// 正常
break;
case ResultAPI::AuthV4ConflictPlayer:
// 账户冲突
// 例如) 使用 Hive UI 时
// AuthV4::Helper::showConflict(...);
// 或者
// 例如) 实现 GameUI 时
// AuthV4::Helper::resolverConflict(...);// 选择当前用户时
// AuthV4::Helper::switchAccount(...);// 选择切换用户时
break;
default:
// 其他异常
break;
}
});
API 参考: 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 -> {
// 正常
}
ResultAPI.Code.AuthV4ConflictPlayer -> {
// 账户冲突
// 例如) 使用 Hive UI 时
// AuthV4.Helper.showConflict(...);
// 或
// 例如) 实现 GameUI 时
// AuthV4.Helper.resolverConflict(...);// 选择当前用户时
// AuthV4.Helper.switchAccount(...);// 选择用户切换时
}
else -> {
// 其他异常
}
}
}
})
API 参考: 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:
// 正常
break;
case AuthV4ConflictPlayer:
// 账户冲突
// 例如) 使用 Hive UI 时
// AuthV4.Helper.INSTANCE.showConflict(...);
// 或
// 例如) 实现 GameUI 时
// AuthV4.Helper.INSTANCE.resolverConflict(...);// 选择当前用户时
// AuthV4.Helper.INSTANCE.switchAccount(...);// 选择用户切换时
break;
default:
// 其他异常
break;
}
});
API 参考: 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 current user
// AuthV4Interface.helper().switchAccount(...);// When selecting user switch
default:
// Other exceptions
break
}
}
API 参考: [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:
// 成功
break;
case HIVEResultAPICodeAuthV4ConflictPlayer:
// 账户冲突
// 例如) 使用 Hive UI 时
// [[HIVEAuthV4 helper] showConflict: ...];
// 或
// 例如) 实现 GameUI 时
// [[HIVEAuthV4 helper] resolverConflict:...];// 选择当前用户时
// [[HIVEAuthV4 helper] switchAccount:...];// 选择用户切换时
break;
default:
// 其他异常
break;
}
}];
游客登录¶
游客登录功能允许用户在不选择 IdP 的情况下以游客模式玩游戏。可以从 Hive SDK 提供的显式登录 UI 中选择游客,或者如果在游戏中直接自定义,也可以实现游客登录。Windows 环境不支持游客登录。
作为访客登录时,您必须遵守以下政策。
客户登录政策¶
- 实现游戏,使得 IdP 认证用户和访客用户可以以相同的方式使用它。 即使以访客身份登录,Hive 平台的大多数功能也可以使用。因此,请确保以访客身份登录的用户可以像 IdP 关联用户一样使用游戏。例如,访客用户也应该能够在游戏中购买物品和进行支付。
- 不为访客用户提供注销功能。 如果用户在以访客身份登录后注销,他们将无法使用相同的 PlayerID 重新登录。因此,当用户以访客身份登录时,不要提供注销按钮,以防止他们注销。
- 中国的访客登录政策禁止 使用中国 IP 时,只有经过实名认证的用户才能充值和消费资源(自 2017 年 5 月 1 日起生效),因此访客登录不包括在可以使用中国 IP 登录的 IdP 列表中。
要执行访客登录,请调用signIn()
方法,并将ProviderType.GUEST
作为参数。
以下是执行访客登录的示例代码。
Note
The PlayerID在没有任何IdP认证的访客状态下,在playerInfo中没有providerInfoData。
API 参考: hive.AuthV4.signIn
API 参考: Auth4::signIn
API 参考: AuthV4.signIn
API 参考: com.hive.Auth4.signIn
API 参考: AuthV4Interface.signIn
API 参考: HIVEAuth4:signIn
自定义登录¶
自定义登录是一个功能,允许您实现与游戏本身集成的身份提供者(IdP)进行登录,除了Hive提供的IdP。尝试创建一个身份验证密钥(authKey),以便在调用自定义登录API时使用,具体请参阅Authenticate v4 Custom Authentication。
在调用自定义登录 API 后,您可以通过作为回调接收到的 PlayerInfo 类的实例访问 customProviderInfoData
数据,以检查自定义登录用户的信息。 customProviderInfoData
的 ProviderType (枚举) 统一设置为 CUSTOM
,并可以通过 ProviderName (字符串) 进行详细区分。
在游戏中实现自定义登录的 IdP 的信息不包含在调用 AuthV4
类的 setup()
和 showSignIn()
方法的结果中。
如果在第一次执行自定义登录后收到了
playerId
和playerToken
,则在重新调用自定义登录 API 时,authV4SessionExist(code)
的结果 API 将作为回调返回。在这种情况下,您应该使用ProviderType.Auto
作为参数调用signIn()
,以使用已登录的帐户进行自动登录。请参阅下面的示例代码。
AuthV4
类的connect()
和disconnect()
方法不支持自定义登录 IdP 的额外集成和断开连接。自定义登录 IdP 的额外集成和断开连接由connectWithAuthKey()
和disconnectWithName()
方法支持。
这是一个实现自定义登录的示例代码。
API 参考: hive.AuthV4.signIn
// Twitter 登录直接在游戏中实现
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"];
// 检查以下用户链接信息
providerInfo.providerType; // ProviderType.CUSTOM,自定义类型是固定的,因此需要通过 providerName 区分
providerInfo.providerName; // "CUSTOM_TWITTER"
providerInfo.providerUserId; // 用于直接实现的 Twitter 登录的用户 ID
return;
}
else if (result.code == ResultAPI.Code.AuthV4SessionExist) {
// 如果 playerId 和 playerToken 已经被发放,并且需要自动登录
// TODO: AuthV4.signIn(ProviderType.AUTO, (ResultAPI _result, PlayerInfo playerInfo) => {});
}
else if (result.code == ResultAPI.Code.AuthV4NotInitialized) {
// TODO: 需要 SDK 初始化
}
else if (result.code == ResultAPI.Code.AuthV4InvalidParam) {
// TODO: 检查提供的 authKey 的值是否为 NULL 或空
}
else if (result.needExit()) {
// TODO: 实现应用退出功能
// 例如 Application.Quit();
}
});
});
#include "HiveAuthV4.h"
// 在游戏中直接实现了 "CUSTOM_TWITTER" 类型的 Twitter 登录
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, custom types have fixed Type
FString ProviderName = ProviderInfo->ProviderName; // Need to distinguish by ProviderName
FString ProviderUserId = ProviderInfo->ProviderUserId; // User id used in the custom Twitter login
}
} else if (Result.NeedExit()) {
// TODO: 实现应用程序退出功能
// e.g.) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
} else if (Result.Code == FHiveResultAPI::ECode::AuthV4SessionExist) {
// 如果 playerId 和 playerToken 已经被发放,并且需要自动登录
// TODO: FHiveAuthV4.SignIn(EHiveProviderType::GUEST, Delegate);
} else if (Result.Code == FHiveResultAPI::ECode::AuthV4NotInitialized) {
// TODO: 需要 SDK 初始化
} else if (Result.Code == FHiveResultAPI::ECode::AuthV4InvalidParam) {
// TODO: 检查提供的 authKey 的值是否为空
}
}));
}
API 参考: Auth4::signIn
using namespace std;
using namespace hive;
// Twitter 登录直接在游戏中实现
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"];
// 检查以下用户链接信息
providerInfo.providerType; // ProviderType::CUSTOM,自定义类型是固定的,因此需要通过 providerName 区分
providerInfo.providerName; // "CUSTOM_TWITTER"
providerInfo.providerUserId; // 用于自定义 Twitter 登录的用户 ID
return;
}
else if (result.code == ResultAPI::Code::AuthV4SessionExist) {
// 如果 playerId 和 playerToken 已经被发放,并且需要自动登录
// TODO: AuthV4.signIn(ProviderType::AUTO, [=](ResultAPI const & _result, PlayerInfo const & playerInfo) {});
}
else if (result.code == ResultAPI::Code::AuthV4NotInitialized) {
// TODO: 需要 SDK 初始化
}
else if (result.code == ResultAPI::Code::AuthV4InvalidParam) {
// TODO: 检查提供的 authKey 的值是否为 NULL 或空
}
else if (result.needExit()) {
// TODO: 实现应用退出功能
// 对于 Cocos2d-x 引擎用户
// 示例) exit(0);
// 对于 Unreal 引擎用户
// 示例) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
}
});
});
API 参考: com.hive.Auth4.signIn
// 游戏中直接实现的Twitter登录
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, custom types are fixed, so need to distinguish by providerName
providerInfo.providerName // "CUSTOM_TWITTER"
providerInfo.providerUserId // User id used for the custom Twitter login
}
}
else if (result.needExit()) {
// TODO: 实现应用程序退出功能
// e.g.) exitProcess(0)
}
else if (result.code == ResultAPI.Code.AuthV4SessionExist) {
// 如果 playerId 和 playerToken 已经被发放并且需要自动登录
// TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener)
}
else if (result.code == ResultAPI.Code.AuthV4NotInitialized) {
// TODO: 需要 SDK 初始化
}
else if (result.code == ResultAPI.Code.AuthV4InvalidParam) {
// TODO: 检查提供的 authKey 的值是否为 NULL 或空
}
}
})
}
API 参考: 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");
// 检查以下用户链接信息
if (providerInfo != null){
providerInfo.getProviderType(); // AuthV4.ProviderType.CUSTOM, 自定义类型由类型固定,因此需要通过providerName区分
providerInfo.getProviderName(); // "CUSTOM_TWITTER"
providerInfo.getProviderUserId(); // 用于自定义Twitter登录的用户ID
}
} else if (result.needExit()) {
// TODO: 实现应用退出功能
// e.g.) System.exit(0);
} else if (result.getCode() == ResultAPI.Code.AuthV4SessionExist) {
// 如果playerId和playerToken已经被发放并且需要自动登录
// TODO: AuthV4.signIn(AuthV4.ProviderType.AUTO, authV4SignInListener)
} else if (result.getCode() == ResultAPI.Code.AuthV4NotInitialized) {
// TODO: 需要SDK初始化
} else if (result.getCode() == ResultAPI.Code.AuthV4InvalidParam) {
// TODO: 检查提供的authKey的值是否为NULL或空
}
}
});
}
API 参考: HIVEAuth4:signIn
// 在游戏中直接实现Twitter登录
Game.login("CUSTOM_TWITTER") { (authKey) in
AuthV4Interface.signInWithAuthKey(authKey) { (result, playerInfo) in
if result.isSuccess() {
let customProviderInfoData = playerInfo?.customProviderInfoData;
let providerInfo = customProviderInfoData?["CUSTOM_TWITTER"]
// 检查以下用户链接信息
providerInfo?.providerType; // AuthProviderType,自定义类型是固定的,因此需要通过providerName区分
providerInfo?.providerName; // "CUSTOM_TWITTER"
providerInfo?.providerUserId; // 用于自定义Twitter登录的用户ID
return
}
else if result.getCode() == .authV4SessionExist {
// 如果playerId和playerToken已经被发放并且需要自动登录
// TODO: AuthV4Interface.signIn(.auto) { (result, playerInfo) in }
}
else if result.getCode() == .authV4NotInitialized {
// TODO: 需要SDK初始化
}
else if result.getCode() == .authV4invalidParam {
// TODO: 检查提供的authKey的值是否为nil或空
}
else if result.needExit() {
// TODO: 实现应用程序退出功能。
// 示例) exit(0)
}
}
}
API 参考: HIVEAuth4:signIn
// 在游戏中直接实现Twitter登录
[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"];
// 检查以下用户链接信息
providerInfo.providerType; // HIVEProviderTypeCustom,自定义类型是固定的,因此需要通过providerName区分
providerInfo.providerName; // "CUSTOM_TWITTER"
providerInfo.providerUserId; // 用于自定义Twitter登录的用户ID
return;
}
else if (result.getCode == HIVEResultAPICodeAuthV4SessionExist) {
// 如果playerId和playerToken已经被发放,并且需要自动登录
// TODO: [HIVEAuthV4 signIn:HIVEProviderTypeAuto, handler:^(HIVEResultAPI* _result, HIVEPlayerInfo* playerInfo) {}];
}
else if (result.getCode == HIVEResultAPICodeAuthV4NotInitialized) {
// TODO: 需要SDK初始化
}
else if (result.getCode == HIVEResultAPICodeAuthV4InvalidParam) {
// TODO: 检查提供的authKey的值是否为NULL或为空
}
else if (result.needExit) {
// TODO: 实现应用退出功能。
// 例如)exit(0);
}
}];
}];
用户名¶
由于美国的COPPA等问题,从美国及其领土访问并作为身份提供者登录时,您必须输入用户名以启用额外的用户身份验证处理。作为参考,包含在美国领土中的国家有美属萨摩亚(AS)、关岛(GU)、北马里亚纳群岛(MP)、波多黎各(PR)、美国本土外小岛屿(UM)和美属维尔京群岛(VI)。输入用户身份的用户名的屏幕如下。
- 用户名输入屏幕仅用于用户识别目的,因此仅在初始 IdP 集成期间显示一次,之后将不再显示。
- 在访客登录期间,用户名输入屏幕不会显示。
验证身份验证令牌密钥¶
游戏服务器可以使用成功登录后返回的令牌、playerId 和 DID 信息来验证身份验证令牌密钥的有效性。Hive 身份验证允许多设备登录和并发访问。
如果不允许使用相同账户重复访问,游戏服务器将在首次连接的设备上显示通知消息,然后终止游戏,并确保游戏在后连接的设备上保持。在这种情况下,如果在不终止游戏的情况下发生重复访问,游戏记录可能无法正确反映。要实现此功能,您需要管理一个经过验证的令牌密钥或使用它管理游戏本身的会话密钥。
请参考身份验证令牌密钥验证服务器 API以实现此功能。
在后台检测 IdP 账户更改¶
用户可以在游戏过程中导航到设备设置以更改他们的 Apple Game Center 或 Google Play 游戏账户。如果您需要检查游戏过程中 IdP 账户是否与当前 PlayerID 关联的 IdP 账户不同,请在初始化 SDK 后调用 setProviderChangedListener()
。通过调用此 API,当游戏恢复时,您将收到一个事件,指示设备上设置的 IdP 账户已更改。
iOS在Apple Game Center账户更改时运行,Android在Google Play Games账户更改时运行,只有当前登录的PlayerID与该IdP关联时才会发送响应。当接收到IdP账户更改事件时,UI会配置为允许用户选择是否使用设备上登录的IdP账户。如果用户选择设备上登录的IdP账户,则调用signOut
进行注销,然后执行隐式登录。
Warning
由于Google Play游戏的操作问题,2021年7月之后发布的安装了Google Play游戏的设备无法在后台更改IdP帐户。
Note
此功能可能会导致游戏玩法中断并请求账户更改,仅在需要账户同步时(例如进入大厅或商店时)才能限制使用。
以下是一个示例代码,用于在用户重新启动游戏并且设备上设置的 IdP 账户发生更改时接收事件。
API 参考: 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) {
// 更改 Google Play 游戏服务帐户
}
});
API 参考: 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) {
// 更改 Google Play 游戏服务帐户
}
}
})
API Reference: HIVEAuthV4:setProviderChangedListener
游戏数据初始化¶
在初始化游戏数据时不要调用注销。由于 PlayerID 未被删除,可能会发生账户之间的冲突。您应该实现用户可以继续使用当前登录的账户进行游戏,并且在用户明确请求之前不要调用注销。
登出¶
Warning
- 登出时,身份验证信息 PlayerId 和会话信息 PlayerToken,以及所有 IDP 会话信息,将被删除。
- 所有以 set 开头的 API 设置的值将不会被初始化或删除。
- Configuration、Auth、Auth v4、Promotion 和 Push 类中所有以 set 开头的方法
- 以下是代表性的示例。 ex> Configuration.setServer, Configuration.setUseLog, Configuration.setGameLanguage, Configuration.setHiveCertificationKey, Auth.setEmergencyMode, AuthV4.setProviderChangedListener, Promotion.setUserEngagementReady, Promotion.setAddtionalInfo, Push.setRemotePush, Push.setForegroundPush 等。所有以 set 开头的方法均属于此类别。
- 从 Hive SDK v4 24.3.0 开始,当访客用户登出时,将返回错误代码。之后,客户端和服务器会话将保持。
- 通过 SDK 中以 set 开头的方法设置的值的有效范围在应用程序的生命周期内保持,无论登录或登出状态如何。
如果您已登录Hive,则已发放PlayerID和身份验证令牌密钥。注销是初始化PlayerID和身份验证令牌密钥的功能。当您调用signOut()
方法完成注销时,您将被重定向到游戏标题,点击标题时将执行明确的登录。
Note
- 在访客登录状态下注销时,无法再找到相同的 PlayerID,因此请实现访客状态下不提供注销功能。
- PlayerID 的 IdP 关联状态在注销后不会改变。
- 一旦注销完成,将导航到游戏标题,点击标题时将执行显式登录。
- 注销后,重新启动应用时将首先执行隐式登录。
这是一个执行注销的示例代码。
API 参考: 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:
// 登出成功
break;
default:
// 其他异常
break;
}
}));
API 参考: AuthV4::signOut
API 参考: AuthV4.Helper.signOut
API 参考: AuthV4.Helper.INSTANCE.signOut
API 参考: [HIVEAuthV4 helper] 登出
游戏中心取消通知文本¶
语言 | 短语 |
---|---|
韩语 | Apple Game Center 登录已被取消。 请在 [设置 > Game Center] 登录以与您的 Game Center 帐户同步,然后重试。 |
英语 | 您对 Game Center 的登录已被取消。 在 [设置> Game Center] 登录以同步到 Game Center 帐户,然后重试。 |
日语 | Apple Game Center ログインがキャンセルされました。 Game Center アカウントと連動するには [設定 > Game Center] にログインした後、再度お試しください。 |
简体中文 | Apple Game Center 已注销。 如果您想与 Game Center 帐户同步,请在设备上重新登录 [设置>Game Center],然后重试。 |
繁体中文 | 登入Apple Game Center已取消。 若想連動Game Center帳號,請至[設定 > Game Center]登入後,再試一次。 |
法语 | 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. |
德语 | 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. |
俄语 | Ваш авторизация в Game Center была отменена. Авторизуйтесь в Game Center через [Настройки > Game Center] и повторите попытку. |
西班牙语 | 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. |
葡萄牙语 | 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. |
印尼语 | Login ke Apple Game Center telah dibatalkan. Hubungkan akun Game Center dengan login di [Pengaturan > Game Center] dan coba lagi. |
马来语 | Log masuk ke Game Center anda telah dibatalkan. Log masuk di [Tetapan>Game Center] untuk disegerakkan ke Akaun Game Center dan cuba lagi. |
越南语 | Đã 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. |
泰语 | การล็อกอินเข้า Game Center ของคุณถูกยกเลิก ล็อกอินที่ [การตั้งค่า>Game Center] เพื่อเชื่อมต่อบัญชี Game Center และโปรดลองอีกครั้ง |
意大利语 | 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. |
土耳其语 | 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. |
阿拉伯语 | تم إلغاء تسجيل الدخول إلى مركز الألعاب. سجل الدخول إلى [الإعدادات> مركز الألعاب] للمزامنة مع حساب مركز الألعاب وحاول مرة أخرى。 |