跳轉至

登录注销

登入 登出

Note
  • 提供的助手版本為 SDK v4.7.0。要使用早於 SDK 4.7.0 的版本,請參閱此頁面。
  • 有關 AuthV4.Helper 的更多描述,請參考 Authentication 頁面。

登入

登入驗證由以下步驟組成。

  1. 自動登入和隱式登入
  2. 明確登入
  3. 檢查設備上的已登入 IdP 帳戶
  4. 訪客登入

Authv4Helper 執行登錄過程的某些部分,並根據響應指示正確的頁面。

請參考以下註解以實現登錄功能。

Note

蘋果不支持 iOS 企業版的 Apple Game Center 和應用內購買。因此,在 iOS 企業版中無法使用 Apple Game Center 帳戶進行隱式登錄,也無法在顯式登錄狀態下使用 Apple Game Center。

Note
  • 如果您的遊戲目標是13歲以下的兒童,則Google Build的隱式登錄不可用,因為無法應用Google Play遊戲服務。欲了解更多信息,請參見Google Play遊戲服務質量檢查清單

  • 确保仅在用户首次登录您的游戏时处理 Google Play 游戏的隐式登录。有关更多信息,请参阅 Google 开发者指南中的 1.5 记住玩家是否拒绝登录

Note
  • 在中國,因為 Google Play 遊戲在該國被禁止,隱式登錄在 Android 上不可用。
  • Facebook 不在 IdP 列表中,因為 Facebook 在中國不可用。
  • 如果用戶使用中國 IP 訪問遊戲,只有授權成員可以充值遊戲金錢或購買物品(自 2017 年 5 月 1 日起)。因此,在中國 IP 中,訪客登錄被排除在可以登錄的 IdP 列表之外。
Note

當使用者取消登入 Apple Game Center 時,iOS 不會顯示登入畫面。因此,可以透過在 AuthV4Helper 類別中實作 showGameCenterLoginCancelDialog() 方法,直接從 SDK 或遊戲工作室顯示通知短語。如果 AuthV4.signIn(AuthV4.ProviderType.APPLE, ...)AuthV4.connect(AuthV4.ProviderType.APPLE, ...) 的回調結果為取消,則可以使用 Game Center 登入禁用的通知短語。提供短語以指導使用者如何再次與 Game Center 帳戶同步。

Note

如果在用户设备上未使用 Apple ID 登录而尝试使用 Apple 登录,则在调用 AuthV4Helper 类中的 connect()signIn() 方法时,会发生 AuthV4SignInAppleUnknown 错误。在这种情况下,会自动弹出一个 Apple ID 登录的通知弹窗,因此游戏工作室无需调用任何内容。

自動登入和隱式登入

自動登入

隱式登入是一種用戶不選擇登入方式,而是自動登入iOS上的Apple Game Center帳戶或Android上的Google Play Games帳戶的方法。在自動登入失敗後執行隱式登入。

離線模式

Hive SDK v4 23.1.0 及更高版本提供自動登錄功能(AuthV4.signIn 使用 ProviderType.AUTO,或 AuthV4.Helper.signIn),即使用戶的設備未連接到網絡。要使用離線模式,請遵循以下說明:

  1. 必須至少在在線模式下運行應用程序一次,並成功進行明確、隱式、訪客或自定義登錄,隨後發放了 playerIdplayerToken
    從應用程序開發者的角度來看,必須至少成功執行過一次 AuthV4.Helper.signInAuthV4.showSignInAuthV4.signInWithAuthKey,並在在線狀態下通過回調接收 playerIdplayerToken。從用戶的角度來看,他們必須在設備連接到網絡時至少成功登錄過一次應用程序。然而,如果用戶的帳戶在他們上次在線登錄嘗試期間被暫停或限制,他們將無法在離線模式下登錄。

  2. App Center > Manage Project > Game Details > Hive Product Settings中的Hive 控制台啟用離線模式。

Windows上的自動登錄

Windows 環境支持自動登錄,並且可以在Hive 控制台應用中心中啟用/禁用。請注意,Windows 的自動登錄與移動環境的自動登錄工作方式不同。它們的區別是:

  • 在移動環境中,使用者透過自動登入保持登入狀態,但在Windows中,只有當使用者啟用「保持我登入」的選項框(在登入UI中的IdP列表下方顯示)時,才會保持登入。在其他情況下,登入狀態不會持續。
  • 在移動環境中,當您執行 AuthV4Helper.Connect 並轉換到另一個帳戶時,新的登入帳戶也會透過自動登入保持登入狀態,但在Windows中則不會。

隱式登入

  • 隱式登錄的登錄流程

AuthV4.Helper.signIn 嘗試通過使用 PlayerID 的身份驗證令牌密鑰進行自動登錄。如果從先前登錄生成的令牌密鑰不存在,則遊戲會自動在 iOS 的 Apple Game Center 和 Android 的 Google Play Games 中登錄。如果登錄失敗,則根據響應顯示適當的登錄頁面。

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"

// 嘗試 Hive SDK 登入 (signIn)
FHiveAuthV4::Helper::SignIn(FHiveAuthV4HelperDelegate::CreateLambda([this](const FHiveResultAPI& Result, const TOptional<FHivePlayerInfo>& 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 FHiveResultAPI::ECode::AuthV4ConflictPlayer:
                                // 帳戶衝突
                                break;
                        case FHiveResultAPI::ECode::AuthV4HelperImplifiedLoginFail:
                                // 隱式登入失敗
                                // 例如) AuthV4.showSignIn(...);)
                                break;
                        default:
                                // 其他例外
                                break;
                }
        }
}));

API 參考: Auth4::signIn

// 嘗試 Hive SDK 登入 (signIn)
AuthV4::Helper::signIn([=](ResultAPI const & result, std::shared\_ptr playerInfo) {

if (result.isSuccess()) {
// 登入成功
} else if (result.needExit()) {
// TODO: 實現應用程式退出功能
// Cocos2d-x 引擎的用戶
// ex) exit(0);
// Unreal 引擎用戶
// 例) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
} else {
switch(result.code) {
case ResultAPI::AuthV4ConflictPlayer:
// 帳戶衝突
break;
case ResultAPI::AuthV4HelperImplifiedLoginFail:
// 隱式登入失敗
// ex) AuthV4.showSignIn(...);
break;
default:
break;
}
}
});

API 參考: com.hive.Auth4.Helper.signIn

// 嘗試 Hive SDK 登錄 (signIn)
AuthV4.Helper.signIn(object : AuthV4.Helper.AuthV4HelperListener {
    override fun onAuthV4Helper(result: ResultAPI, playerInfo: AuthV4.PlayerInfo?) {
        if (result.isSuccess) {
            // 登錄成功
        } else if (result.needExit()) {
            // TODO: 實現應用退出功能
            // ex) exitProcess(0)
        } else {
            when (result.code) {
                ResultAPI.Code.AuthV4ConflictPlayer -> {
                    // 帳戶衝突
                }
                ResultAPI.Code.AuthV4HelperImplifiedLoginFail -> {
                    // 隱式登錄失敗
                    // ex) AuthV4.showSignIn(...);
                }
                else -> {
                    // 其他異常
                }
            }
        }
    }
})

API 參考: com.hive.Auth4.signIn

// 嘗試 Hive SDK 登入 (signIn)
AuthV4.Helper.signIn(new AuthV4.Helper.AuthV4HelperListener() {
    @Override
    public void onAuthV4Helper(ResultAPI result, AuthV4.PlayerInfo playerInfo) {

        if (result.isSuccess()) {
            // 登入成功
        } else if (result.needExit()) {
            // TODO: 實現應用程式退出功能
            // ex) System.exit(0);
        } else {
            switch(result.code) {
                case AuthV4ConflictPlayer:
                    // 帳號衝突
                    break;
                case AuthV4HelperImplifiedLoginFail:
                    // 隱式登入失敗
                    // ex) AuthV4.showSignIn(...);
                    break;
                default:
                    // 其他例外
                    break;
            }
        }
    }
});

API 參考: AuthV4Interface.signIn

// 嘗試 Hive SDK 登入 (signIn)
AuthV4Interface.helper().signIn() { (result, playerInfo) in

    if result.isSuccess() {
        // 登入成功
    }
    else if result.needExit() {
        // TODO: 實現應用程式退出功能
        // ex) exit(0)
    }
    else {
        switch result.getCode() {
        case .authV4ConflictPlayer:
            // 帳戶衝突
        case .authV4HelperImplifiedLoginFail:
            // 隱式登入失敗
            // ex) AuthV4Interface.showSignIn() { (result, playerInfo)
            // // 做一些事情...
            // }
        default:
            // 其他例外
            break
        }
    }
}

API 參考: HIVEAuth4: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 提供的 UI 或在使用身份提供者 (IdP) 列表初始化 Hive SDK 後在遊戲中自定義的 UI 組成。如果您自定義 UI,請參見 自定義明確登錄 UI

Hive 平台根據各國的政策控制並提供 IdP 列表。例如,Google Play 遊戲、Facebook 和訪客登錄在中國不可用。

一個明確登錄的示例畫面

由 Hive SDK 提供的 IdP 選擇 UI


當使用 Hive SDK 提供的 UI 實現該功能時

要使用 Hive SDK 提供的 UI 實現明確登錄,您可以通過調用 showSignIn() 方法顯示 IdP 列表 UI。

Note

确保在用户点击 SDK 提供的 IdP 选择 UI 中的 X 按钮关闭后,提供再次登录的方法。因为用户尚未登录。

Note

如果您想自定義明確登錄,請參見這裡

API 參考: hive.AuthV4.showSignIn

<code>    
    // 请求 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: Implement the termination of the app    
        // Example) Application.Quit();    
    }    
});
#include "HiveAuthV4.h"

// 請求 Hive SDK AuthV4 認證 UI
FHiveAuthV4::ShowSignIn(FHiveAuthV4OnSignInDelegate::CreateLambda([this](const FHiveResultAPI& Result, const FHivePlayerInfo& PlayerInfo) {
        if (Result.IsSuccess()) {
                // 認證成功 

                 // 獲取電子郵件信息的示例
                for (const auto& ProviderInfoEntry : PlayerInfo.ProviderInfoData) {
                        FHiveProviderInfo ProviderInfo = ProviderInfoEntry.Value;
                        FString Email = ProviderInfo.ProviderEmail;
                }
        } else if (Result.NeedExit()) {
                // TODO: 實現應用程序的終止    
        // Cocos2d-x 引擎的用戶    
        // 例如) exit(0);    
        // Unreal 引擎用戶    
        // 示例) UKismetSystemLibrary::QuitGame(GetWorld(), nullptr, EQuitPreference::Quit, false);
        }
}));

API 參考: AuthV4::showSignIn

// 請求 Hive SDK AuthV4 認證 UI    
    AuthV4::showSignIn([=](ResultAPI const & result, PlayerInfo const & playerInfo) {    
    if (result.isSuccess()) {     
        // 認證成功     
        // playerInfo: 已認證的用戶信息    
        // 獲取電子郵件信息的示例    
        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: 實現應用程序的終止    
            // ex) exitProcess(0)    
        }    
    }    
})

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:showSignIn

var email = String()    
    // Request Hive SDK AuthV4 Authentication 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 = @"";    
    // 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);    
    }    
}];

自訂明確登錄 UI

您可以通过使用 providerTypeList 来实现自定义的显式登录 UI,该列表作为 AuthV4.setup() 方法的回调处理程序返回,该方法在 Hive SDK 初始化时调用,或者在 Hive SDK 初始化后调用 AuthV4.Helper.getIDPList() 方法。当您希望根据游戏 UI 显示登录屏幕,或仅显示与特定 IdP 的链接选项时,使用自定义显式登录 UI。设计完 UI 后,根据用户的操作调用 signIn() 方法,并传入所需的 ProviderType。

Note
  • 範例 UI 只在登入頁面顯示 Facebook 同步的按鈕

以下是用戶在自定義明確登錄 UI 上選擇 Google 登錄的情況下的示例代碼。

API 參考: 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.

                // 示例:搜索 ProviderType::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()) {    
             // call successful    
             // playerInfo: Authenticated user information.    

             // 提供者類型::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) {    
                 // 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 參考: 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 參考: AuthV4Interface.signIn

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

            // 供應商類型::GOOGLE 的電子郵件資訊搜尋範例  
            if     
                let playerInfo = playerInfo,    
                let providerInfo = playerInfo.providerInfoData["GOOGLE"] {    
                    let email = providerInfo.providerEmail    
            }    
        }    
}

API 參考: HIVEAuth4:signIn

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

             // HIVEProviderTypeGoogle 的電子郵件資訊搜尋範例    
             if(playerInfo != nil) {    
                 HIVEProviderInfo *providerInfo = playerInfo.providerInfoData[@"GOOGLE"];    
                 if(providerInfo != nil){    
                     NSString *email = providerInfo.providerEmail;    
                 }    
             }    
         }    
}];

檢查設備上的已登錄 IdP 帳戶

自動登錄可用於使用註冊的 playerId 的令牌密鑰登錄,明確登錄也可以使用各種 IdP。在這兩種情況下,用戶設備上登錄的 IdP 帳戶(DevicePlayer)可能與用戶登錄的 PlayerID 的 IdP 不匹配。考慮到成就或排行榜的使用,提供了通知頁面以便用戶匹配兩個帳戶。

  • 提供 SDK 的 UI,詢問是否使用 DevicePlayer

以下是確認 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:
                        // normal
                        break;
                case FHiveResultAPI::ECode::AuthV4ConflictPlayer:
                        // 帳號衝突    
                        // 例如) 當使用 Hive UI   
                        // AuthV4::Helper::showConflict(...);    
                        //或    
                        // 例如) 當實作 GameUI    
                        // AuthV4::Helper::resolverConflict(...);// 當選擇當前用戶    
                        // AuthV4::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 -> {    
                     // normal    
                 }    
                 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 the current user    
             // AuthV4Interface.helper().switchAccount(...);// When selecting user switch    
           default:    
    // other exception situations    
             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;    
    }    
}];

來賓登入

Hive SDK 支持访客登录,允许用户在不选择 IdP 的情况下以访客身份使用游戏。您可以通过 Hive SDK 提供的显式登录 UI,或通过游戏的自定义 UI 实现此功能,让用户选择访客。Windows 环境不支持访客登录。

請確保在以訪客身份登錄時遵守以下政策。

客戶登入政策

  • 建立一個對於訪客用戶和 Hive 會員同樣可用的遊戲。

    Hive 平台的大多數功能對於訪客用戶都是可用的。因此,請為訪客用戶和 IdP 連接的用戶實現相同的遊戲。例如,訪客用戶也可以購買物品並在遊戲中付款。

  • 不允許訪客用戶登出。

    如果用戶以訪客身份登錄然後登出,則該用戶將無法使用相同的 PlayerID 再次登錄。因此,請不要提供登出按鈕,以防止用戶在其狀態為訪客時登出。

  • 訪客登錄政策與中國IP。

    如果用户使用中国IP访问游戏,只有授权成员可以充值游戏币或购买物品(从2017年5月1日起)。因此,使用中国IP可用的IdP不包括访客登录。

實現 signIn() 方法,參數為 ProviderType.GUEST 以執行訪客登錄。 以下是執行訪客登錄的範例代碼。

Note

在沒有 IdP 認證的來賓狀態下的 PlayerID 沒有 playerInfo 的 providerInfoData。

API 參考: hive.AuthV4.signIn

using hive;    
    AuthV4.signIn(AuthV4.ProviderType.GUEST, (ResultAPI result, AuthV4.PlayerInfo playerInfo) => {    
         if (result.isSuccess()) {    
             // 身份验证成功    
             // playerInfo: 已验证的用户信息    
         }    
});
#include "HiveAuthV4.h"

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

        if (Result.IsSuccess()) {
                // 認證成功    
      // playerInfo: 已認證的用戶信息 
        }
}));

API 參考: 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()) {    
        // 认证成功    
        // playerInfo: 认证用户信息    
        }    
});

API 參考: 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) {    
                 // 認證成功    
                 // playerInfo: 認證用戶信息    
             }    
         }    
})

API 參考: com.hive.Auth4.signIn

import com.hive.AuthV4;    
    import com.hive.ResultAPI;    
    AuthV4.INSTANCE.signIn(AuthV4.ProviderType.GUEST, (result, playerInfo) -> {    
         if (result.isSuccess()) {    
             // 认证成功    
             // playerInfo: 认证用户信息    
         }    
});

API 參考: AuthV4Interface.signIn

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

API 參考: HIVEAuth4:signIn

#import <HIVEService/HIVEService-Swift.h>    
    [HIVEAuthV4 signIn: HIVEProviderTypeGuest handler: ^(ResultAPI *result, HIVEPlayerInfo *playerInfo) {    
        if ([result isSuccess]) {    
        // 认证成功    
        // playerInfo: 认证用户信息    
        }    
}];

自訂登入

自訂登入 是一個實現與外部 IdP 登入的功能,該功能是 Hive SDK 不支援的。請遵循 Auth V4 自訂身份驗證 指南來創建一個 authKey,用於調用自訂登入 API。 您可以通過訪問 customProviderInfoData 來確認使用自訂登入簽入的用戶的信息,該信息與作為自訂登入 API 的回調傳遞的 PlayerInfo 對象一起使用。 customProviderInfoDataProviderType(enum) 均設置為 CUSTOM,並可以通過 ProviderName(String) 進行詳細識別。

  • 實現自定義登錄的 IdP 的信息不包括在調用 setup()showSignIn() 方法的 AuthV4 類的結果中。
  • 如果在第一次執行自定義登錄後獲得 playerIdplayerToken,則 authV4SessionExist(code) 的結果 API 將作為回調在重新調用自定義登錄 API 時傳遞。在這種情況下,使用參數 ProviderType.Auto 實現 signIn() 方法,以使用先前的登錄帳戶執行自動登錄。
  • connect()disconnect() 方法的 AuthV4 類目前不支持自定義登錄 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"

// 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, 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) {
                        // 如果您需要在已经发出 playerId 和 playerToken 后自动登录    
            // TODO: AuthV4.signIn(ProviderType::AUTO, [=](ResultAPI const & _result, PlayerInfo const & playerInfo) {});
                } else if (Result.Code == FHiveResultAPI::ECode::AuthV4NotInitialized) {
                        // TODO: 需要初始化 SDK 
                } else if (Result.Code == FHiveResultAPI::ECode::AuthV4InvalidParam) {
                        // TODO: 需要检查传递的 authKey 值是否为 NULL 或为空
                }
        }));
}

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 引擎的用戶    
            // ex) 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, 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 參考: com.hive.Auth4.signIn

// Twitter 登入直接在遊戲中實現
    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: 實現應用程序退出功能
                            // ex) 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

swift // 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: 實現應用程序關閉功能。 // ex) 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: 實現應用程序關閉功能。
                            // ex) exit(0);
                    }
    }];
    }];

用戶名

由於美國COPPA等問題,當從美國或其領土訪問並使用IdP登錄時,您必須輸入您的用戶名以啟用額外用戶識別的身份驗證。作為參考,包含在美國領土中的國家有美屬薩摩亞(AS)、關島(GU)、北馬里亞納群島(MP)、波多黎各(PR)、美國小島嶼(UM)和美國維爾京群島(VI)。用戶識別的用戶名輸入屏幕如下。

  • 使用者名稱輸入畫面僅用於用戶識別,因此僅在首次與 IdP 連結時顯示一次,並且在此之外不會顯示。
  • 以訪客身份登錄時,使用者名稱輸入畫面不會顯示。

驗證身份驗證令牌密鑰

遊戲伺服器可以通過使用返回的令牌、playerId 和 DID 資訊來驗證身份驗證令牌密鑰,這是在成功登錄後進行的。身份驗證允許多設備登錄和重複連接。

除非您的遊戲允許使用一個 ID 進行重複訪問,否則遊戲伺服器會在已登錄的設備上發出通知並終止遊戲。然後,第二個登錄的設備保持其遊戲進行的登錄狀態。如果用戶在不終止一個設備上的遊戲的情況下保持重複連接,則遊戲進行可能無法準確記錄。因此,請確保管理已驗證的令牌密鑰,或通過使用令牌密鑰管理遊戲本身的會話密鑰來實現此功能。

透過參考Hive 伺服器 API > 驗證身份 v4 令牌來實現該函數。

獲取 TalkPlus 登入令牌

要登入 TalkPlus,您需要在通過 Auth v4 介面登入 (signIn()) 後,調用 AuthV4.getHiveTalkPlusLoginToken API 獲得的登入令牌。(請參見 TalkPlus 登入指南)

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
    }
}];

在背景中檢測 IdP 帳戶的變更

用戶可以在遊玩遊戲時通過設備設置更改其 Apple Game Center 或 Google Play 遊戲帳戶。如果您需要檢查 IdP 帳戶是否與當前 PlayerID 連接的帳戶匹配,請在初始化 Hive SDK 後實現 setProviderChangedListener()。如果您實現了該 API,用戶可以在遊戲恢復時接收到通知用戶設備上 IdP 帳戶變更的事件。

當更改 Apple Game Center 中的帳戶時,iOS 可以正常運作,而當更改 Google Play Games 中的帳戶時,Android 可以正常運作。只有當當前登錄的 PlayerID 與相關的 IdP 連接時,才會發送響應。如果您在 IdP 帳戶中收到更改事件,請配置用戶界面,讓用戶選擇是否使用設備上登錄的 IdP 帳戶。如果用戶選擇設備上登錄的 IdP 帳戶,請調用 signOut 以登出並進行隱式登錄。

Warning

由於 Google Play 遊戲的工作問題,2021 年 7 月之後發布的 Google Play 遊戲設備無法在背景中更改 IdP 帳戶。

Note

此功能可能會停止播放並要求更改用戶帳戶,因此僅在需要帳戶同步時使用;訪問大廳或商店。

以下是示例代码,用于接收当玩家恢复游戏时,IdP帐户设置在设备上更改的事件。

API 參考: hive.AuthV4.setProviderChangedListener

using hive;

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

    if (providerInfo != null && providerInfo.providerType == AuthV4.ProviderType.APPLE) {
        // 更改 GameCenter 用戶信息
    }
});
#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 參考: 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 參考 : : 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) {
        // 更改 Google Play 游戏服务帐户
    }
});

API 參考: AuthV4Interface .setProviderChangedListener

import HIVEService

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

    如果 let providerInfo = providerInfo, providerInfo.providerType == .Apple {
    // 更改 GameCenter 用户信息
    }
}

API 參考: HIVEAuthV4:setProviderChangedListener

#import <HIVEService/HIVEService-Swift.h>

[HIVEAuthV4 setProviderChangedListener: ^(HIVEResultAPI *result, ProviderInfo *providerInfo) {
if (![result isSuccess]) {
return;
}
    if (providerInfo != nil && providerInfo.providerType == HIVEProviderTypeApple) {
    // 更改 GameCenter 用户信息
    }
}];

初始化遊戲數據

確保在初始化遊戲數據時不要實現登出。PlayerID不會通過初始化被刪除,因此可能會導致帳戶之間的崩潰。讓用戶使用當前登錄的帳戶玩遊戲,並且在用戶明確要求點擊登出按鈕之前,不要實現登出功能。

登出

Warning
  • 登出時,PlayerId(身份驗證信息)、PlayerToken(會話信息)和所有 IDP 會話信息將被刪除。
  • 登出時,使用 setter API(set API 系列)設置的值不會被初始化或刪除。
    • Configuration、Auth、Auth v4、Promotion 和 Push 類中的每個 setter 方法
    • 例如:Configuration.setServer, Configuration.setUseLog, Configuration.setGameLanguage, Configuration.setHiveCertificationKey, Auth.setEmergencyMode, AuthV4.setProviderChangedListener, Promotion.setUserEngagementReady, Promotion.setAddtionalInfo, Push.setRemotePush, Push.setForegroundPush 等等。
    • 從 Hive SDK v4 24.3.0 開始,當訪客用戶登出時將返回錯誤代碼。客戶端和服務器會話將在此後保持。
  • setter 方法設置的值的有效範圍在應用程序的生命週期內維持,而不是在登錄或登出狀態下。

如果已進行登錄,則已經發出 PlayerID 和身份驗證令牌密鑰。登出負責初始化 PlayerID 和令牌密鑰。如果通過實現 signOut() 完成登出,則移動到遊戲標題,並在用戶點擊標題時執行顯式登錄。

Note
  • 當用戶狀態為訪客時,實現不提供登出功能,因為訪客登出後無法找到相同的 PlayerID。
  • 即使用戶登出,IdP 與 PlayerID 的連接狀態也不會改變。
  • 當用戶登出時,轉到遊戲標題。當玩家點擊標題時,執行明確登錄。
  • 如果用戶在登出後重新啟動遊戲應用程序,則應執行隱式登錄。

以下是實現登出的示例代碼。

API 參考: hive.AuthV4.signOut

using hive;    

    AuthV4.Helper.signOut (delegate (ResultAPI result, AuthV4.PlayerInfo playerInfo) {    
         switch(result.code) {    
             case ResultAPI.Code.Success:    
                 // 登出成功    
                 break;    
             default:    
                 // 其他异常情况    
                 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:
                        // 登出成功
                        break;
                default:
                        // 其他异常情况
                        break;
        }
}));

API 參考: 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:    
                 // 登出成功    
                 break;    
             default:    
                 // 其他异常情况    
                 break;    
         }    
});

API 參考: 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 -> {
                // 登出成功
            }
            else -> {
                // 其他异常情况
            }
        }
    }
})

API 参考: AuthV4.Helper.INSTANCE.signOut

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

AuthV4.Helper.INSTANCE.signOut((result, playerInfo) -> {
    switch (result.getCode()) {
        case Success:
            // 登出成功
            break;
        default:
            // 其他异常情况
            break;
    }
});

API 參考: AuthV4Interface.helper().signOut()

import HIVEService

AuthV4Interface.helper().signOut() { result, playerInfo in
    switch result.getCode() {
        case .success:
            // 登出成功
        default:
            // 其他异常情况
            break
    }}

API 參考: [HIVEAuthV4 helper] signOut

#import <HIVEService/HIVEService-Swift.h>

[[HIVEAuthV4 helper] signOut: ^(HIVEResultAPI *result, HIVEPlayerInfo *playerInfo) {
    switch ([result getCode]) {
        case HIVEResultAPICodeSuccess:
            // 登入成功
            break;
        default:
            // 其他异常情况
            break;
    }
}];

遊戲中心登入禁用的通知短語

語言 短語
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 تم إلغاء تسجيل الدخول إلى مركز الألعاب.
سجل الدخول إلى [الإعدادات >; مركز الألعاب] للمزامنة مع حساب مركز الألعاب وحاول مرة أخرى。