This document describes additional features supported by Gamebase.
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS ■ UNREAL_WINDOWS
FString GetDeviceLanguageCode() const;
[Note]
Gamebase client messages are available in English (en), Korean (ko), and Japanese (ja) only.
| Code | Name |
|---|---|
| de | German |
| en | English |
| es | Spanish |
| fi | Finnish |
| fr | French |
| id | Indonesian |
| it | Italian |
| ja | Japanese |
| ko | Korean |
| pt | Portuguese |
| ru | Russian |
| th | Thai |
| vi | Vietnamese |
| ms | Malay |
| zh-CN | Chinese-Simplified |
| zh-TW | Chinese-Traditional |
Each language code is defined in the GamebaseDisplayLanguageCode class.
[Caution]
Gamebase-supported language codes are case-sensitive. Settings like 'EN' or 'zh-cn' may cause trouble.
namespace GamebaseDisplayLanguageCode
{
static const FString German(TEXT("de"));
static const FString English(TEXT("en"));
static const FString Spanish(TEXT("es"));
static const FString Finnish(TEXT("fi"));
static const FString French(TEXT("fr"));
static const FString Indonesian(TEXT("id"));
static const FString Italian(TEXT("it"));
static const FString Japanese(TEXT("ja"));
static const FString Korean(TEXT("ko"));
static const FString Portuguese(TEXT("pt"));
static const FString Russian(TEXT("ru"));
static const FString Thai(TEXT("th"));
static const FString Vietnamese(TEXT("vi"));
static const FString Malay(TEXT("ms"));
static const FString Chinese_Simplified(TEXT("zh-CN"));
static const FString Chinese_Traditional(TEXT("zh-TW"));
}
Display Language can be configured when Gamebase is initialized.
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS
void Initialize(const FGamebaseConfiguration& configuration, const FGamebaseLaunchingInfoDelegate& onCallback);
Example
void USample::Initialize(const FString& AppID, const FString& AppVersion)
{
FGamebaseConfiguration Configuration;
...
Configuration.DisplayLanguageCode = DisplayLanguage;
...
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->Initialize(Configuration, FGamebaseLaunchingInfoDelegate::CreateLambda([Subsystem](const FGamebaseLaunchingInfo* LaunchingInfo, const FGamebaseError* Error)
{
if (Gamebase::IsSuccess(Error))
{
UE_LOG(LogTemp, Display, TEXT("Initialize succeeded."));
FString DisplayLanguage = Subsystem->GetDisplayLanguageCode();
}
else
{
UE_LOG(LogTemp, Display, TEXT("Initialize failed."));
}
}));
}
Display Language can be changed from Gamebase initialization.
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS ■ UNREAL_WINDOWS
void SetDisplayLanguageCode(const FString& languageCode);
Example
void USample::SetDisplayLanguageCode(const FString& DisplayLanguage)
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->SetDisplayLanguageCode(DisplayLanguage);
}
Current Display Language can be queried.
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS ■ UNREAL_WINDOWS
FString GetDisplayLanguageCode() const;
Example
void USample::GetDisplayLanguageCode()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
FString DisplayLanguage = Subsystem->GetDisplayLanguageCode();
}
Regarding how to add new language sets on Unreal Android or iOS platform, see the following guides:
When Display Language is set by initialization or SetDisplayLanguageCode API, the final value might be different from actual input.
en is automatically set for Display Language. API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS
FString GetCountryCodeOfUSIM() const;
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS
FString GetCountryCodeOfDevice() const;

API
■ UNREAL_ANDROID ■ UNREAL_IOS
FString GetCountryCode() const;
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS ■ UNREAL_WINDOWS
FDelegateHandle AddHandler(const FGamebaseEventDelegate::FDelegate& Callback);
void RemoveHandler(const FDelegateHandle& handle);
void RemoveAllHandler();
VO
struct GAMEBASE_API FGamebaseEventMessage
{
// Represents the type of an event.
// The value of the GamebaseEventCategory class is assigned.
FString Category;
// JSON String data that can be converted into a VO that is appropriate for each category.
FString Data;
};
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::IdPRevoked))
{
auto IdpRevokedData = FGamebaseEventIdPRevokedData::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::LoggedOut))
{
auto LoggedOutData = FGamebaseEventLoggedOutData::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::ServerPushAppKickOut) ||
Message.Category.Equals(GamebaseEventCategory::ServerPushAppKickOutMessageReceived) ||
Message.Category.Equals(GamebaseEventCategory::ServerPushTransferKickout))
{
auto ServerPushData = FGamebaseEventServerPushData::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::ObserverLaunching))
{
auto ObserverData = FGamebaseEventObserverData::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::ObserverNetwork))
{
auto ObserverData = FGamebaseEventObserverData::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::ObserverHeartbeat))
{
auto ObserverData = FGamebaseEventObserverData::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::PurchaseUpdated))
{
auto PurchasableReceipt = FGamebaseEventPurchasableReceipt::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::PushReceivedMessage))
{
auto PushMessage = FGamebaseEventPushMessage::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::PushClickMessage))
{
auto PushMessage = FGamebaseEventPushMessage::From(Message.Data);
}
else if (Message.Category.Equals(GamebaseEventCategory::PushClickAction))
{
auto PushAction = FGamebaseEventPushAction::From(Message.Data);
}
}));
}
Event type |
GamebaseEventCategory | VO conversion method | Remarks |
|---|---|---|---|
| IdPRevoked | GamebaseEventCategory::IdPRevoked | FGamebaseEventIdPRevokedData::From(Message.Data) | - |
| LoggedOut | GamebaseEventCategory::LoggedOut | FGamebaseEventLoggedOutData::From(Message.Data) | - |
| ServerPush | GamebaseEventCategory::ServerPushAppKickOut GamebaseEventCategory::ServerPushAppKickOutMessageReceived GamebaseEventCategory::ServerPushTransferKickout |
FGamebaseEventServerPushData::From(Message.Data) | - |
| Observer | GamebaseEventCategory::ObserverLaunching GamebaseEventCategory::ObserverNetwork GamebaseEventCategory::ObserverHeartbeat |
FGamebaseEventObserverData::From(Message.Data) | - |
| Purchase - Promotion payment - Pending payment |
GamebaseEventCategory::PurchaseUpdated | FGamebaseEventPurchasableReceipt::From(Message.Data) | - |
| Push - Message received |
GamebaseEventCategory::PushReceivedMessage | FGamebaseEventPushMessage::From(Message.Data) | |
| Push - Message clicked |
GamebaseEventCategory::PushClickMessage | FGamebaseEventPushMessage::From(Message.Data) | |
| Push - Action clicked |
GamebaseEventCategory::PushClickAction | FGamebaseEventPushAction::From(Message.Data) | Operates when the RichMessage button is clicked. |
[Note]
This is an event that can only occur when using iOS Appleid login.
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::IdPRevoked))
{
// TODO: process logout, then login again.
}
}));
}
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::LoggedOut))
{
auto LoggedOutData = FGamebaseEventLoggedOutData::From(Message.Data);
if (loggedData.IsValid() == true)
{
// There was a problem with the access token.
// Call login again.
}
}
}));
}
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::ServerPushAppKickOut) ||
Message.Category.Equals(GamebaseEventCategory::ServerPushAppKickOutMessageReceived) ||
Message.Category.Equals(GamebaseEventCategory::ServerPushTransferKickout))
{
auto serverPushData = FGamebaseEventServerPushData::From(Message.Data);
if (serverPushData.IsVaild())
{
CheckServerPush(Message.Category, *serverPushData);
}
}
}));
}
void USample::CheckServerPush(const FString& Category, const FGamebaseEventServerPushData& Data)
{
if (Message.Category.Equals(GamebaseEventCategory::ServerPushAppKickOut))
{
// Kicked out from Gamebase server.(Maintenance, banned or etc.)
// And the game user closes the kickout pop-up.
// Return to title and initialize Gamebase again.
}
else if (Message.Category.Equals(GamebaseEventCategory::ServerPushAppKickOutMessageReceived))
{
// Currently, the kickout pop-up is displayed.
// If your game is running, stop it.
}
else if (Message.Category.Equals(GamebaseEventCategory::ServerPushTransferKickout))
{
// If the user wants to move the guest account to another device,
// if the account transfer is successful,
// the login of the previous device is released,
// so go back to the title and try to log in again.
}
}
struct GAMEBASE_API FGamebaseEventObserverData
{
// This information represents the status value.
int32 Code;
// This information shows the message about status.
FString Message;
// A reserved field for additional information.
FString Extras;
}
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::ObserverLaunching))
{
auto observerData = FGamebaseEventObserverData::From(Message.Data);
if (observerData.IsVaild())
{
CheckLaunchingStatus(*observerData);
}
}
else if (Message.Category.Equals(GamebaseEventCategory::ObserverNetwork))
{
auto observerData = FGamebaseEventObserverData::From(Message.Data);
if (observerData.IsVaild())
{
CheckNetwork(*observerData);
}
}
else if (Message.Category.Equals(GamebaseEventCategory::ObserverHeartbeat))
{
auto observerData = FGamebaseEventObserverData::From(Message.Data);
if (observerData.IsVaild())
{
CheckHeartbeat(*observerData);
}
}
}));
}
void USample::CheckLaunchingStatus(const FGamebaseEventObserverData& Data)
{
switch (Data.code)
{
case GamebaseLaunchingStatus::IN_SERVICE:
{
// Service is now normally provided.
break;
}
// ...
case GamebaseLaunchingStatus::INTERNAL_SERVER_ERROR:
{
// Error in internal server.
break;
}
}
}
void USample::CheckNetwork(const FGamebaseEventObserverData& Data)
{
switch ((GamebaseNetworkType)Data.code)
{
case EGamebaseNetworkType::Not:
{
// Network disconnected.
break;
}
case EGamebaseNetworkType::Mobile:
case EGamebaseNetworkType::Wifi:
case EGamebaseNetworkType::Any:
{
// Network connected.
break;
}
}
}
void USample::CheckHeartbeat(const FGamebaseEventObserverData& Data)
{
switch (Data.code)
{
case EGGamebaseErrorCode::INVALID_MEMBER:
{
// You can check the invalid user session in here.
// ex) After transferred account to another device.
break;
}
case EGGamebaseErrorCode::BANNED_MEMBER:
{
// You can check the banned user session in here.
break;
}
}
}
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::PurchaseUpdated))
{
auto purchasableReceipt = FGamebaseEventPurchasableReceipt::From(Message.Data);
if (purchasableReceipt.IsVaild())
{
// If the user got item by 'Promotion Code' or
// 'Lazy purchase', or 'Parents permission',...,
// this event will be occurred.
}
}
}));
}
VO
struct FGamebaseEventPushMessage
{
// The unique ID of a message.
FString Id;
// The title of the push message.
FString Title;
// The body of the push message.
FString Body;
// You can check the custom information sent when sending a push in JSON format.
FString Extras;
};
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::PushReceivedMessage))
{
auto PushMessage = FGamebaseEventPushMessage::From(Message.Data);
if (PushMessage.IsVaild())
{
// When you clicked push Message.
// By converting the extras field of the push Message to JSON,
// you can get the custom information added by the user when sending the push.
// (For Android, an 'isForeground' field is included so that you can check if received in the foreground state.)
}
}
}));
}
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::PushClickMessage))
{
auto PushMessage = FGamebaseEventPushMessage::From(Message.Data);
if (PushMessage.IsVaild())
{
// When you clicked push Message.
}
}
}));
}
VO
struct FGamebaseEventPushAction
{
// Button action type.
FString ActionType;
// PushMessage data.
FGamebaseEventPushMessage Message;
// User text typed in Push console.
FString UserText;
};
Example
void USample::AddEventHandler()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->AddEventHandler(FGamebaseEventDelegate::FDelegate::CreateLambda([](const FGamebaseEventMessage& Message)
{
if (Message.Category.Equals(GamebaseEventCategory::PushClickAction))
{
auto PushAction = FGamebaseEventPushAction::From(Message.Data);
if (PushAction.IsVaild())
{
// When you clicked action button by 'Rich Message'.
}
}
}));
}
Game indicators can be sent to Gamebase Server.
[Caution]
All APIs supported by Gamebase Analytics can be called after login.
[TIP]
When a purchase is completed by calling RequestPurchase API, indicators are automatically deliverd.
Regarding the usage of Analytics Console, see the following guide:
Level information of a game user can be delivered to indicators, after a user login.
[Caution]
If SetGameUserData API is not called after a login to game, level information might be missing from other indicators.
Following parameters are required to call APIs:
FGamebaseAnalyticsUserData
| Name | Mandatory(M) / Optional(O) | Type | Desc. |
|---|---|---|---|
| UserLevel | M | int32 | Refers to the level of a game user. |
| ChannelId | O | FString | Indicates a channel. |
| CharacterId | O | FString | Refers to the name of a character. |
| CharacterClassId | O | FString | Indicates an occupation. |
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS ■ UNREAL_WINDOWS
void SetGameUserData(const FGamebaseAnalyticsUserData& GameUserData);
Example
void USample::SetGameUserData(int32 UserLevel, const FString& ChannelId, const FString& CharacterId, const FString& CharacterClassId)
{
FGamebaseAnalyticsUserData GameUserData;
GameUserData.UserLevel = UserLevel;
GameUserData.ChannelId = ChannelId;
GameUserData.CharacterId = CharacterId;
GameUserData.CharacterClassId = CharacterClassId;
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->GetAnalytics()->SetGameUserData(GameUserData);
}
Updated level information of a game user can be delivered to indicators.
Following paratemers are required to call APIs:
LevelUpData
| Name | Mandatory(M) / Optional(O) | Type | Desc. |
|---|---|---|---|
| UserLevel | M | int32 | Refers to the level of a game user. |
| LevelUpTime | M | int64 | Enter by Epoch Time. Enter by the millisecond. |
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS ■ UNREAL_WINDOWS
void TraceLevelUp(const FGamebaseAnalyticesLevelUpData& levelUpData);
Example
void USample::TraceLevelUpNow(int32 UserLevel)
{
FGamebaseAnalyticesLevelUpData levelUpData{ UserLevel, FDateTime::Now().ToUnixTimestamp() };
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->GetAnalytics()->TraceLevelUp(levelUpData);
}
Gamebase provides features for customer response.
[TIP]
By integrating with NHN Cloud Contact, customer inquiries can be handled with more ease and convenience.
For more details on NHN Cloud Contact, see the guide as below: NHN Cloud Online Contact Guide
In the Gamebase Console > App > Customer service, you can choose from three different types of Customer Centers.

| Customer Service Type | Required Login |
|---|---|
| Developer customer center | X |
| Gamebase customer center | △ |
| NHN Cloud Online Contact | O |
Gamebase SDK's Customer Center API uses the following URLs based on the type:
Displays the Customer Center WebView. URL is determined by the customer center type. You can pass the additional information to the URL using ContactConfiguration.
FGamebaseContactConfiguration
| Parameter | Mandatory(M) / Optional(O) |
Values | Description |
|---|---|---|---|
| UserName | O | FString | User name (nickname) default: "" |
| AdditionalURL | O | FString | Additional URL appended to the developer's own customer center URL default: "" |
| AdditionalParameters | O | TMap |
Additional parameters appended to the customer center URL default : EmptyMap |
| ExtraData | O | TMap |
Passes the extra data wanted by the developer when opening the customer center default: EmptyMap |
API
Supported Platforms ■ UNREAL_ANDROID ■ UNREAL_IOS ■ UNREAL_WINDOWS
void OpenContact(const FGamebaseErrorDelegate& onCloseCallback);
void OpenContact(const FGamebaseContactConfiguration& Configuration, const FGamebaseErrorDelegate& onCloseCallback);
ErrorCode
| Error Code | Description |
|---|---|
| NOT_INITIALIZED(1) | Gamebase.initialize has not been called. |
| NOT_LOGGED_IN(2) | The customer center type is 'NHN Cloud OC', and it was called before login. |
| UI_CONTACT_FAIL_INVALID_URL(6911) | The Customer Center URL does not exist. Check the Customer Center URL of the Gamebase Console. |
| UI_CONTACT_FAIL_ISSUE_SHORT_TERM_TICKET(6912) | Failed to issue a temporary ticket for user identification. |
| UI_CONTACT_FAIL_ANDROID_DUPLICATED_VIEW(6913) | The Customer Center WebView is already being displayed. |
Example
void USample::OpenContact()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->GetContact()->OpenContact(FGamebaseErrorDelegate::CreateLambda([Subsystem](const FGamebaseError* Error)
{
if (Gamebase::IsSuccess(Error))
{
UE_LOG(LogTemp, Display, TEXT("OpenContact succeeded."));
}
else
{
UE_LOG(LogTemp, Display, TEXT("OpenContact failed. (errorCode: %d, errorMessage: %s)"), Error->Code, *Error->Message);
if (Error->Code == GamebaseErrorCode::WEBVIEW_INVALID_URL)
{
// Gamebase Console Service Center URL is invalid.
// Please check the url field in the NHN Cloud Gamebase Console.
auto LaunchingInfo = Subsystem->GetLaunching().GetLaunchingInformations();
UE_LOG(LogTemp, Display, TEXT("csUrl: %s"), *LaunchingInfo->Launching.App.RelatedUrls.CsUrl);
}
}
}));
}
[Caution]
Contacting the Customer Center may require file attachment. To do so, permissions for using the camera or using the storage must be acquired from the user at runtime.
Android user
For Unreal, activate the built-in Android Runtime Permission plugin in the engine, and then refer to the following API Reference to acquire necessary permissions. Unreal API Reference : AndroidPermission
iOS user
- Please set 'Privacy - Camera Usage Description', 'Privacy - Photo Library Usage Description' in info.plist.
Returns the URL used for displaying the Customer Center WebView.
API
void RequestContactURL(const FGamebaseContactUrlDelegate& Callback);
void RequestContactURL(const FGamebaseContactConfiguration& Configuration, const FGamebaseContactUrlDelegate& Callback);
ErrorCode
| Error Code | Description |
|---|---|
| NOT_INITIALIZED(1) | Gamebase.initialize has not been called. |
| NOT_LOGGED_IN(2) | The customer center type is 'NHN Cloud OC', and it was called before login. |
| UI_CONTACT_FAIL_INVALID_URL(6911) | The Customer Center URL does not exist. Check the Customer Center URL of the Gamebase Console. |
| UI_CONTACT_FAIL_ISSUE_SHORT_TERM_TICKET(6912) | Failed to issue a temporary ticket for user identification. |
Example
void USample::RequestContactURL(const FString& userName)
{
FGamebaseContactConfiguration Configuration{ userName };
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->GetContact()->RequestContactURL(Configuration, FGamebaseContactUrlDelegate::CreateLambda([](FString url, const FGamebaseError* Error)
{
if (Gamebase::IsSuccess(Error))
{
// Open webview with 'contactUrl'
UE_LOG(LogTemp, Display, TEXT("RequestContactURL succeeded. (url = %s)"), *url);
}
else
{
UE_LOG(LogTemp, Display, TEXT("RequestContactURL failed. (errorCode: %d, errorMessage: %s)"), Error->Code, *Error->Message);
if (Error->Code == GamebaseErrorCode::UI_CONTACT_FAIL_INVALID_URL)
{
// Gamebase Console Service Center URL is invalid.
// Please check the url field in the TOAST Gamebase Console.
}
else
{
// An Error occur when requesting the contact web view url.
}
}
}));
}
API
Supported Platforms ■ UNREAL_IOS
UENUM(BlueprintType)
enum class EGamebaseAppTrackingAuthorizationStatus : uint8
{
Authorized, // Consent to allow tracking requests from apps, always returns Authorized on devices below iOS 14
Denied, // Denied app tracking authorization
NotDetermined, // App tracking authorization: Not Determined
Restricted, // App tracking authorization: Restricted
Unknown // Other OS or undefined OS status
};
EGamebaseAppTrackingAuthorizationStatus GetAppTrackingAuthorizationStatus();
Example
void USample::GetAppTrackingAuthorizationStatus()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
EGamebaseAppTrackingAuthorizationStatus Status = Subsystem->GetUtil()->GetAppTrackingAuthorizationStatus();
switch (Status)
{
case EGamebaseAppTrackingAuthorizationStatus::Authorized:
break;
case EGamebaseAppTrackingAuthorizationStatus::Denied:
break;
case EGamebaseAppTrackingAuthorizationStatus::NotDetermined:
break;
case EGamebaseAppTrackingAuthorizationStatus::Restricted:
break;
case EGamebaseAppTrackingAuthorizationStatus::Unknown:
break;
}
}
API
Supported Platforms ■ UNREAL_IOS
FString GetIdfa();
Example
void USample::GetIdfa()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
FString Idfa = Subsystem->GetUtil()->GetIdfa();
}
Texas SB 2420 and similar state laws require apps to verify a user's age to protect minors. Gamebase provides an API that wraps the Google Play Age Signals API to meet this requirement.
For instructions on setting up the Age Signals feature on Android, please refer to the following documentation.
Check the age information.
API
Supported Platforms ■ UNREAL_ANDROID
void GetAgeSignal(const FGamebaseAgeSignalResultDelegate& Callback);
ErrorCode
| Error Code | Description |
|---|---|
| NOT_SUPPORTED(10) | Called on devices with Android API lower than version 23. |
| AUTH_EXTERNAL_LIBRARY_ERROR(3009) | The Google Play Age Signals API returned an error. |
Handle results
You can check a user's status using the UserStatus property of FGamebaseAgeSignalResult. Please determine whether to restrict the user based on the Status value.
EGamebaseAgeSignalsVerificationStatus
A user validation status constant.
| Status | Description |
|---|---|
| Verified | Adults 18 years of age or older |
| Supervised | Minors with parental consent |
| SupervisedApprovalPending | Pending parental approval |
| SupervisedApprovalDenied | Parental approval denied |
| Unknown | Unverified user |
Example
void USample::GetAgeSignal()
{
UGamebaseSubsystem* Subsystem = UGameInstance::GetSubsystem<UGamebaseSubsystem>(GetGameInstance());
Subsystem->GetUtil()->GetAgeSignal(
FGamebaseAgeSignalResultDelegate::CreateLambda([](const FGamebaseAgeSignalResult* AgeSignalResult, const FGamebaseError* Error)
{
if (Gamebase::IsSuccess(Error))
{
if (!AgeSignalResult->UserStatus.IsSet())
{
// It means that the user is not located in a regulated area (Texas, Utah, and Louisiana).
// You can proceed with your app's logic for non-regulated users.
UE_LOG(LogTemp, Display, TEXT("Not legally applicable"));
}
else
{
EGamebaseAgeSignalsVerificationStatus UserStatus =
static_cast<EGamebaseAgeSignalsVerificationStatus>(AgeSignalResult->UserStatus.GetValue());
switch (UserStatus)
{
case EGamebaseAgeSignalsVerificationStatus::Verified:
{
// Adult users 18 years of age or older
// Allow access to all features
// AgeLower and AgeUpper are not set
UE_LOG(LogTemp, Display, TEXT("Age 18 or older"));
break;
}
case EGamebaseAgeSignalsVerificationStatus::Supervised:
{
// Minors with parental consent
// Limited features for minors under Texas SB 2420
// You can check the age range.
if (AgeSignalResult->AgeLower.IsSet() && AgeSignalResult->AgeUpper.IsSet())
{
int32 AgeLower = AgeSignalResult->AgeLower.GetValue(); // e.g. 13
int32 AgeUpper = AgeSignalResult->AgeUpper.GetValue(); // e.g.17
UE_LOG(LogTemp, Display, TEXT("Supervised user, age range: %d - %d"), AgeLower, AgeUpper);
}
if (AgeSignalResult->InstallId.IsSet())
{
FString InstallId = AgeSignalResult->InstallId.GetValue();
UE_LOG(LogTemp, Display, TEXT("InstallId: %s"), *InstallId);
}
break;
}
case EGamebaseAgeSignalsVerificationStatus::SupervisedApprovalPending:
{
// Limited feature is available while waiting for parental approval.
// Notify the user that approval is pending.
if (AgeSignalResult->MostRecentApprovalDate.IsSet())
{
int64 ApprovalDate = AgeSignalResult->MostRecentApprovalDate.GetValue();
UE_LOG(LogTemp, Display, TEXT("Approval pending since: %lld"), ApprovalDate);
}
break;
}
case EGamebaseAgeSignalsVerificationStatus::SupervisedApprovalDenied:
{
// If your guardian refuses permission,
// you will be notified that only limited features are available or the service is unavailable.
UE_LOG(LogTemp, Display, TEXT("Parent or guardian has denied changes"));
break;
}
case EGamebaseAgeSignalsVerificationStatus::Unknown:
{
// If the user is not verified in your jurisdiction, or age verification information is unavailable,
// ask the user to visit the Play Store to resolve the issue.
UE_LOG(LogTemp, Display, TEXT("User is not verified or supervised"));
break;
}
}
}
}
else
{
UE_LOG(LogTemp, Display, TEXT("GetAgeSignal failed. (errorCode: %d, errorMessage: %s)"), Error->Code, *Error->Message);
if (Error->Code == GamebaseErrorCode::NOT_SUPPORTED)
{
// Not supported on devices with Android API lower than version 23.
UE_LOG(LogTemp, Display, TEXT("Age Signals API is not supported on this device"));
}
else if (Error->Code == GamebaseErrorCode::AUTH_EXTERNAL_LIBRARY_ERROR)
{
// An error occurred in Google Play Services.
UE_LOG(LogTemp, Display, TEXT("Google Play Age Signals error"));
}
}
}));
}