├── .gitignore
├── img
└── blueprint.png
├── .gitattributes
├── GameAnalytics
├── .DS_Store
├── Source
│ ├── .DS_Store
│ ├── ThirdParty
│ │ ├── .DS_Store
│ │ ├── GA-SDK-CPP
│ │ │ ├── .DS_Store
│ │ │ └── lib
│ │ │ │ ├── .DS_Store
│ │ │ │ ├── Mac
│ │ │ │ └── libGameAnalytics.a
│ │ │ │ ├── Win64
│ │ │ │ └── GameAnalytics.lib
│ │ │ │ └── Linux-clang
│ │ │ │ └── libGameAnalytics.a
│ │ └── lib
│ │ │ ├── ios
│ │ │ └── libGameAnalytics.a
│ │ │ └── html5
│ │ │ └── GameAnalyticsUnreal.js
│ ├── GameAnalytics
│ │ ├── .DS_Store
│ │ ├── Private
│ │ │ ├── .DS_Store
│ │ │ ├── GameAnalyticsPerformance.h
│ │ │ ├── GameAnalyticsPerformance.cpp
│ │ │ ├── GameAnalyticsProvider.h
│ │ │ ├── Desktop
│ │ │ │ ├── GAWrapperCpp.h
│ │ │ │ └── GAWrapperCpp.cpp
│ │ │ ├── IOS
│ │ │ │ ├── GAWrapperIOS.h
│ │ │ │ └── GAWrapperIOS.mm
│ │ │ ├── Android
│ │ │ │ └── GAWrapperAndroid.h
│ │ │ ├── GameAnalyticsModule.cpp
│ │ │ ├── GameAnalyticsProvider.cpp
│ │ │ └── GameAnalytics.cpp
│ │ ├── GA-SDK-IOS
│ │ │ └── PrivacyInfo.xcprivacy
│ │ ├── GA-SDK-ANDROID
│ │ │ └── lib
│ │ │ │ ├── gameanalytics.aar
│ │ │ │ └── gameanalytics.jar
│ │ ├── GameAnalytics_iOS_UPL.xml
│ │ ├── Public
│ │ │ ├── GAEnums.h
│ │ │ ├── GameAnalyticsModule.h
│ │ │ ├── GAWrapper.h
│ │ │ └── GameAnalytics.h
│ │ ├── GameAnalytics_APL.xml
│ │ ├── GA-SDK-CPP
│ │ │ └── GameAnalytics
│ │ │ │ ├── GATypes.h
│ │ │ │ └── GameAnalytics.h
│ │ ├── GA-SDK-HTML5
│ │ │ └── GameAnalytics.h
│ │ └── GameAnalytics.Build.cs
│ └── GameAnalyticsEditor
│ │ ├── Private
│ │ ├── GameAnalyticsProjectSettings.cpp
│ │ ├── GameAnalyticsEditor.cpp
│ │ └── GameAnalyticsTargetSettingsCustomization.h
│ │ ├── Public
│ │ ├── GameAnalyticsEditor.h
│ │ └── GameAnalyticsProjectSettings.h
│ │ └── GameAnalyticsEditor.Build.cs
├── Resources
│ └── Icon128.png
├── Config
│ └── FilterPlugin.ini
├── GameAnalytics.uplugin
└── README.md
├── LICENSE
├── README.md
└── CHANGELOG.md
/.gitignore:
--------------------------------------------------------------------------------
1 | GameAnalytics/Binaries/*
2 | GameAnalytics/Intermediate/*
3 |
--------------------------------------------------------------------------------
/img/blueprint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/img/blueprint.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.a filter=lfs diff=lfs merge=lfs -text
2 | *.lib filter=lfs diff=lfs merge=lfs -text
3 |
--------------------------------------------------------------------------------
/GameAnalytics/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/.DS_Store
--------------------------------------------------------------------------------
/GameAnalytics/Source/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/.DS_Store
--------------------------------------------------------------------------------
/GameAnalytics/Resources/Icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Resources/Icon128.png
--------------------------------------------------------------------------------
/GameAnalytics/Source/ThirdParty/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/ThirdParty/.DS_Store
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/GameAnalytics/.DS_Store
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/GameAnalytics/Private/.DS_Store
--------------------------------------------------------------------------------
/GameAnalytics/Source/ThirdParty/GA-SDK-CPP/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/ThirdParty/GA-SDK-CPP/.DS_Store
--------------------------------------------------------------------------------
/GameAnalytics/Source/ThirdParty/GA-SDK-CPP/lib/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/ThirdParty/GA-SDK-CPP/lib/.DS_Store
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GA-SDK-IOS/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/GameAnalytics/GA-SDK-IOS/PrivacyInfo.xcprivacy
--------------------------------------------------------------------------------
/GameAnalytics/Source/ThirdParty/lib/ios/libGameAnalytics.a:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:09907239f51c5e728919d50d2f75fa1d644ec47fc727552a746da1b77ee3a0f4
3 | size 4040752
4 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GA-SDK-ANDROID/lib/gameanalytics.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/GameAnalytics/GA-SDK-ANDROID/lib/gameanalytics.aar
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GA-SDK-ANDROID/lib/gameanalytics.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GameAnalytics/GA-SDK-UNREAL/HEAD/GameAnalytics/Source/GameAnalytics/GA-SDK-ANDROID/lib/gameanalytics.jar
--------------------------------------------------------------------------------
/GameAnalytics/Source/ThirdParty/GA-SDK-CPP/lib/Mac/libGameAnalytics.a:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:15b3522bc253e1da0f531932983d9f28ca73ce272019b6faf9b6cc5129a4036c
3 | size 6423952
4 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/ThirdParty/GA-SDK-CPP/lib/Win64/GameAnalytics.lib:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:160f42d1c2dc6c1eb7f74e90711426f990b4985f2dcd7bead68b8529121ae1af
3 | size 11347588
4 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/ThirdParty/GA-SDK-CPP/lib/Linux-clang/libGameAnalytics.a:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:2f8a5519771c4e41f50c57899dc66e949d367cedc67acf37920749cf1edb8716
3 | size 4397192
4 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GameAnalytics_iOS_UPL.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalyticsEditor/Private/GameAnalyticsProjectSettings.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2 |
3 | #include "GameAnalyticsProjectSettings.h"
4 | #include "GameAnalyticsEditor.h"
5 |
6 |
7 | UGameAnalyticsProjectSettings::UGameAnalyticsProjectSettings( const FObjectInitializer& ObjectInitializer )
8 | : Super( ObjectInitializer )
9 | {
10 | }
--------------------------------------------------------------------------------
/GameAnalytics/Config/FilterPlugin.ini:
--------------------------------------------------------------------------------
1 | [FilterPlugin]
2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and
3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively.
4 | ;
5 | ; Examples:
6 | ; /README.txt
7 | ; /Extras/...
8 | ; /Binaries/ThirdParty/*.dll
9 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalyticsEditor/Public/GameAnalyticsEditor.h:
--------------------------------------------------------------------------------
1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
2 |
3 | #pragma once
4 |
5 | #include "Modules/ModuleManager.h"
6 |
7 | /**
8 | * The public interface to this module
9 | */
10 | class FGameAnalyticsEditor : public IModuleInterface
11 | {
12 | /*public:
13 |
14 | static inline FGameAnalyticsEditor& Get()
15 | {
16 | return FModuleManager::LoadModuleChecked< FGameAnalyticsEditor >("GameAnalyticsEditor");
17 | }*/
18 |
19 | public:
20 | /** IModuleInterface implementation */
21 | void StartupModule();
22 | void ShutdownModule();
23 | };
24 |
--------------------------------------------------------------------------------
/GameAnalytics/GameAnalytics.uplugin:
--------------------------------------------------------------------------------
1 | {
2 | "FileVersion" : 3,
3 |
4 | "FriendlyName" : "GameAnalytics",
5 | "Version" : 1,
6 | "VersionName" : "6.1.0",
7 | "CreatedBy" : "GameAnalytics",
8 | "CreatedByURL" : "http://gameanalytics.com",
9 | "MarketplaceURL" : "com.epicgames.launcher://ue/marketplace/content/d070c3fab7b74c08bab3a89c9cbf4490",
10 | "Description" : "GameAnalytics is a free analytics platform that helps game developers understand their players' behaviour by delivering relevant insights.",
11 | "Category" : "Analytics",
12 |
13 | "Modules" :
14 | [
15 | {
16 | "Name" : "GameAnalytics",
17 | "Type" : "Runtime",
18 | "LoadingPhase" : "PreDefault",
19 | "WhitelistPlatforms" : [ "Android", "IOS", "Mac", "Win64", "Linux" ]
20 | },
21 | {
22 | "Name" : "GameAnalyticsEditor",
23 | "Type" : "UncookedOnly",
24 | "LoadingPhase" : "PreDefault"
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 GameAnalytics
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/GameAnalyticsPerformance.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "GAEnums.h"
4 | #include "Tickable.h"
5 | #include "GenericPlatform/GenericPlatformMisc.h"
6 | #include "GameAnalyticsPerformance.generated.h"
7 |
8 | UCLASS()
9 | class UGameAnalyticsPerformance:
10 | public UObject,
11 | public FTickableGameObject
12 | {
13 | GENERATED_UCLASS_BODY()
14 |
15 | int32 _frameCount = 0;
16 | float _accm = 0.0;
17 | float _avgFps = 0.0;
18 | float _timePassed = 0.0;
19 |
20 | static constexpr float kMaxFpsValue = 120.f;
21 |
22 | public:
23 |
24 | bool EnableFPSTracking = true;
25 |
26 | virtual ~UGameAnalyticsPerformance();
27 |
28 | // returns last fps reading
29 | float GetAvgFps() const;
30 |
31 | // do fps average and reset counter
32 | int32 DoFpsSample();
33 |
34 | virtual void Tick(float DeltaTime) override;
35 |
36 | virtual bool IsTickable() const override;
37 |
38 | virtual bool IsTickableInEditor () const override;
39 |
40 | virtual TStatId GetStatId() const override;
41 |
42 | FString GetGPUModel() const;
43 | };
44 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Public/GAEnums.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "UObject/Object.h"
4 |
5 | UENUM()
6 | enum class EGAResourceFlowType : uint8
7 | {
8 | undefined = 0,
9 | source = 1,
10 | sink = 2
11 | };
12 |
13 | UENUM()
14 | enum class EGAProgressionStatus : uint8
15 | {
16 | undefined = 0,
17 | start = 1,
18 | complete = 2,
19 | fail = 3
20 | };
21 |
22 | UENUM()
23 | enum class EGAErrorSeverity : uint8
24 | {
25 | undefined = 0,
26 | debug = 1,
27 | info = 2,
28 | warning = 3,
29 | error = 4,
30 | critical = 5
31 | };
32 |
33 | UENUM()
34 | enum class EGAAdAction : uint8
35 | {
36 | undefined = 0,
37 | clicked = 1,
38 | show = 2,
39 | failedshow = 3,
40 | rewardreceived = 4,
41 | request = 5,
42 | loaded = 6
43 | };
44 |
45 | UENUM()
46 | enum class EGAAdType : uint8
47 | {
48 | undefined = 0,
49 | video = 1,
50 | rewardedvideo = 2,
51 | playable = 3,
52 | interstitial = 4,
53 | offerwall = 5,
54 | banner = 6
55 | };
56 |
57 | UENUM()
58 | enum class EGAAdError : uint8
59 | {
60 | undefined = 0,
61 | unknown = 1,
62 | offline = 2,
63 | nofill = 3,
64 | internalerror = 4,
65 | invalidrequest = 5,
66 | unabletoprecache = 6
67 | };
68 |
69 | UENUM()
70 | enum class EGAValueType : uint8
71 | {
72 | value_number = 0,
73 | value_string,
74 | value_bool
75 | };
76 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalyticsEditor/GameAnalyticsEditor.Build.cs:
--------------------------------------------------------------------------------
1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
2 |
3 | namespace UnrealBuildTool.Rules
4 | {
5 | public class GameAnalyticsEditor : ModuleRules
6 | {
7 | #if WITH_FORWARDED_MODULE_RULES_CTOR
8 | public GameAnalyticsEditor(ReadOnlyTargetRules Target) : base(Target)
9 | #else
10 | public GameAnalyticsEditor(TargetInfo Target)
11 | #endif
12 | {
13 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
14 |
15 | PrivateDependencyModuleNames.AddRange(
16 | new string[]
17 | {
18 | "Core",
19 | "CoreUObject",
20 | "Engine",
21 | "RenderCore",
22 | "RHI",
23 | "Slate",
24 | "SlateCore",
25 | "EditorStyle",
26 | "EditorWidgets",
27 | "DesktopWidgets",
28 | "PropertyEditor",
29 | "SharedSettingsWidgets",
30 | "SourceControl",
31 | "UnrealEd",
32 | "HTTP",
33 | "Json",
34 | "JsonUtilities",
35 | "InputCore"
36 | }
37 | );
38 |
39 | DynamicallyLoadedModuleNames.AddRange(
40 | new string[]
41 | {
42 | "Settings"
43 | }
44 | );
45 |
46 | PublicIncludePathModuleNames.AddRange(
47 | new string[]
48 | {
49 | "Settings"
50 | }
51 | );
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GameAnalytics_APL.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
20 | -keep class com.gameanalytics.sdk.** { *; }
21 | -keep class android.net.** { *; }
22 | -dontwarn android.net.**
23 |
24 |
25 |
26 |
27 |
28 | repositories {
29 | maven { url 'https://maven.gameanalytics.com/release' }
30 | maven { url 'https://maven.google.com' }
31 | flatDir { dirs("libs") }
32 | }
33 | dependencies {
34 | implementation('com.gameanalytics.sdk:gameanalytics-android:7.0.0')
35 | implementation('com.google.android.gms:play-services-appset:16.0.1')
36 | }
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/GameAnalyticsPerformance.cpp:
--------------------------------------------------------------------------------
1 | #include "GameAnalyticsPerformance.h"
2 |
3 | DEFINE_LOG_CATEGORY_STATIC(LogGameAnalyticsDebug, Display, All);
4 |
5 | void UGameAnalyticsPerformance::Tick(float DeltaTime)
6 | {
7 | _timePassed += DeltaTime;
8 |
9 | float fps = 1.0 / DeltaTime;
10 | _accm += fps;
11 | _frameCount++;
12 |
13 | if(_timePassed >= 1.f)
14 | {
15 | _timePassed = 0.f;
16 | DoFpsSample();
17 | }
18 |
19 | //UE_LOG(LogGameAnalyticsDebug, Display, TEXT("GameAnalytics FPS: %.2f Avg Fps: %.2f"), fps, _avgFps);
20 | }
21 |
22 | float UGameAnalyticsPerformance::GetAvgFps() const
23 | {
24 | if (_avgFps > kMaxFpsValue)
25 | {
26 | return kMaxFpsValue;
27 | }
28 |
29 | return _avgFps;
30 | }
31 |
32 | UGameAnalyticsPerformance::UGameAnalyticsPerformance(const FObjectInitializer& ObjectInitializer) :
33 | UObject(ObjectInitializer), FTickableGameObject()
34 | {
35 | }
36 |
37 | UGameAnalyticsPerformance::~UGameAnalyticsPerformance()
38 | {
39 | }
40 |
41 | FString UGameAnalyticsPerformance::GetGPUModel() const
42 | {
43 | return FPlatformMisc::GetPrimaryGPUBrand();
44 | }
45 |
46 | int32 UGameAnalyticsPerformance::DoFpsSample()
47 | {
48 | if(_accm && _frameCount)
49 | {
50 | _avgFps = _accm / _frameCount;
51 | }
52 |
53 | _accm = 0;
54 | _frameCount = 0;
55 |
56 | return static_cast(_avgFps);
57 | }
58 |
59 | bool UGameAnalyticsPerformance::IsTickable() const
60 | {
61 | return true;
62 |
63 | /*
64 | #if WITH_EDITOR
65 | return false;
66 | #else
67 | return true;
68 | #endif
69 | */
70 | }
71 |
72 | bool UGameAnalyticsPerformance::IsTickableInEditor() const
73 | {
74 | return false;
75 | }
76 |
77 | TStatId UGameAnalyticsPerformance::GetStatId() const
78 | {
79 | return Super::GetStatID();
80 | }
81 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalyticsEditor/Private/GameAnalyticsEditor.cpp:
--------------------------------------------------------------------------------
1 | #include "GameAnalyticsEditor.h"
2 |
3 | #include "GameAnalyticsTargetSettingsCustomization.h"
4 |
5 | #include "Modules/ModuleInterface.h"
6 | #include "ISettingsModule.h"
7 | #include "Modules/ModuleManager.h"
8 |
9 | #include "GameAnalyticsProjectSettings.h"
10 |
11 | #define LOCTEXT_NAMESPACE "GameAnalyticsPlugin"
12 |
13 | void FGameAnalyticsEditor::StartupModule()
14 | {
15 | // register settings detail panel customization
16 | FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked("PropertyEditor");
17 | PropertyModule.RegisterCustomClassLayout(
18 | UGameAnalyticsProjectSettings::StaticClass()->GetFName(),
19 | FOnGetDetailCustomizationInstance::CreateStatic(&FGameAnalyticsTargetSettingsCustomization::MakeInstance)
20 | );
21 |
22 | PropertyModule.NotifyCustomizationModuleChanged();
23 |
24 | ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings");
25 | if( SettingsModule != nullptr )
26 | {
27 | SettingsModule->RegisterSettings(
28 | "Project", "Plugins", "GameAnalytics",
29 | LOCTEXT( "GameAnalyticsSettingsName", "GameAnalytics" ),
30 | LOCTEXT( "GameAnalyticsSettingsDescription", "GameAnalytics settings" ),
31 | GetMutableDefault< UGameAnalyticsProjectSettings >() );
32 | }
33 | }
34 |
35 | void FGameAnalyticsEditor::ShutdownModule()
36 | {
37 | ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings");
38 | if( SettingsModule != nullptr )
39 | {
40 | SettingsModule->UnregisterSettings( "Project", "Plugins", "GameAnalytics" );
41 | }
42 | }
43 |
44 | IMPLEMENT_MODULE(FGameAnalyticsEditor, GameAnalyticsEditor)
45 |
46 | #undef LOCTEXT_NAMESPACE
47 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GA-SDK-CPP/GameAnalytics/GATypes.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | namespace gameanalytics
14 | {
15 | /*!
16 | @enum
17 | @discussion
18 | This enum is used to specify flow in resource events
19 | @constant GAResourceFlowTypeSource
20 | Used when adding to a resource currency
21 | @constant GAResourceFlowTypeSink
22 | Used when subtracting from a resource currency
23 | */
24 | enum EGAResourceFlowType
25 | {
26 | Source = 1,
27 | Sink = 2
28 | };
29 |
30 | /*!
31 | @enum
32 | @discussion
33 | this enum is used to specify status for progression event
34 | @constant GAProgressionStatusStart
35 | User started progression
36 | @constant GAProgressionStatusComplete
37 | User succesfully ended a progression
38 | @constant GAProgressionStatusFail
39 | User failed a progression
40 | */
41 | enum EGAProgressionStatus
42 | {
43 | Start = 1,
44 | Complete = 2,
45 | Fail = 3
46 | };
47 |
48 | /*!
49 | @enum
50 | @discussion
51 | this enum is used to specify severity of an error event
52 | @constant GAErrorSeverityDebug
53 | @constant GAErrorSeverityInfo
54 | @constant GAErrorSeverityWarning
55 | @constant GAErrorSeverityError
56 | @constant GAErrorSeverityCritical
57 | */
58 | enum EGAErrorSeverity
59 | {
60 | Debug = 1,
61 | Info = 2,
62 | Warning = 3,
63 | Error = 4,
64 | Critical = 5
65 | };
66 |
67 | enum EGALoggerMessageType
68 | {
69 | LogError = 0,
70 | LogWarning = 1,
71 | LogInfo = 2,
72 | LogDebug = 3,
73 | LogVerbose = 4
74 | };
75 |
76 | using StringVector = std::vector;
77 |
78 | using LogHandler = std::function;
79 | using FPSTracker = std::function;
80 |
81 | struct IRemoteConfigsListener
82 | {
83 | virtual void onRemoteConfigsUpdated(std::string const& remoteConfigs) = 0;
84 | };
85 | }
86 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GA-SDK-HTML5/GameAnalytics.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | extern "C"
4 | {
5 | void js_configureAvailableCustomDimensions01(const char *list);
6 | void js_configureAvailableCustomDimensions02(const char *list);
7 | void js_configureAvailableCustomDimensions03(const char *list);
8 | void js_configureAvailableResourceCurrencies(const char *list);
9 | void js_configureAvailableResourceItemTypes(const char *list);
10 | void js_configureSdkGameEngineVersion(const char *version);
11 | void js_configureGameEngineVersion(const char *version);
12 | void js_configureBuild(const char *build);
13 | void js_configureUserId(const char *userId);
14 | void js_initialize(const char *gamekey, const char *gamesecret);
15 | void js_setCustomDimension01(const char *customDimension);
16 | void js_setCustomDimension02(const char *customDimension);
17 | void js_setCustomDimension03(const char *customDimension);
18 | void js_addBusinessEvent(const char *currency, int amount, const char *itemType, const char *itemId, const char *cartType, const char *fields);
19 | void js_addResourceEvent(int flowType, const char *currency, float amount, const char *itemType, const char *itemId, const char *fields);
20 | void js_addProgressionEvent(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, const char *fields);
21 | void js_addProgressionEventWithScore(int progressionStatus, const char *progression01, const char *progression02, const char *progression03, int score, const char *fields);
22 | void js_addDesignEvent(const char *eventId, const char *fields);
23 | void js_addDesignEventWithValue(const char *eventId, float value, const char *fields);
24 | void js_addErrorEvent(int severity, const char *message, const char *fields);
25 | void js_setEnabledInfoLog(bool enabled);
26 | void js_setEnabledVerboseLog(bool enabled);
27 | void js_setManualSessionHandling(bool enabled);
28 | void js_setEventSubmission(bool enabled);
29 | void js_startSession();
30 | void js_endSession();
31 | void js_onStop();
32 | const char* js_getRemoteConfigsValueAsString(const char *key);
33 | const char* js_getRemoteConfigsValueAsStringWithDefaultValue(const char *key, const char *defaultValue);
34 | bool js_isRemoteConfigsReady();
35 | const char* js_getRemoteConfigsContentAsString();
36 | const char* js_getABTestingId();
37 | const char* js_getABTestingVariantId();
38 | }
39 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Public/GameAnalyticsModule.h:
--------------------------------------------------------------------------------
1 | // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2 |
3 | #pragma once
4 |
5 | #include "Interfaces/IAnalyticsProviderModule.h"
6 | #include "Interfaces/IAnalyticsProvider.h"
7 | #include "CoreMinimal.h"
8 | #include "Misc/Paths.h"
9 | #include "Runtime/Launch/Resources/Version.h"
10 |
11 | #include "GameAnalytics.h"
12 |
13 | #if (ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 15) || (ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 0)
14 | #include "Modules/ModuleManager.h"
15 | #endif
16 |
17 | /**
18 | * The public interface to this module
19 | */
20 | class FGameAnalyticsModule :
21 | public IAnalyticsProviderModule
22 | {
23 | /** Singleton for analytics */
24 | TSharedPtr GameAnalyticsProvider;
25 |
26 | //--------------------------------------------------------------------------
27 | // Module functionality
28 | //--------------------------------------------------------------------------
29 | public:
30 | /**
31 | * Singleton-like access to this module's interface. This is just for convenience!
32 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
33 | *
34 | * @return Returns singleton instance, loading the module on demand if needed
35 | */
36 | static inline FGameAnalyticsModule& Get()
37 | {
38 | return FModuleManager::LoadModuleChecked< FGameAnalyticsModule >( "GameAnalytics" );
39 | }
40 |
41 | inline UGameAnalytics* GetInstance()
42 | {
43 | return GameAnalytics;
44 | }
45 |
46 | //--------------------------------------------------------------------------
47 | // provider factory functions
48 | //--------------------------------------------------------------------------
49 | public:
50 | /**
51 | * IAnalyticsProviderModule interface.
52 | * Creates the analytics provider given a configuration delegate.
53 | * The keys required exactly match the field names in the Config object.
54 | */
55 | #if (ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 13) || (ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 0)
56 | using Delegate = FAnalyticsProviderConfigurationDelegate;
57 | #else
58 | using Delegate = FAnalytics::FProviderConfigurationDelegate;
59 | #endif
60 |
61 | virtual TSharedPtr CreateAnalyticsProvider(const Delegate& GetConfigValue) const override;
62 |
63 | struct FGameAnalyticsProjectSettings
64 | {
65 | struct PlatformInfo
66 | {
67 | FString GameKey;
68 | FString SecretKey;
69 | FString Build;
70 | };
71 |
72 | PlatformInfo iOS;
73 | PlatformInfo Android;
74 | PlatformInfo Mac;
75 | PlatformInfo Windows;
76 | PlatformInfo Linux;
77 |
78 | TArray CustomDimensions01;
79 | TArray CustomDimensions02;
80 | TArray CustomDimensions03;
81 | TArray ResourceCurrencies;
82 | TArray ResourceItemTypes;
83 |
84 | bool UseManualSessionHandling;
85 | bool AutoDetectAppVersion;
86 | bool DisableDeviceInfo;
87 | bool UseErrorReporting;
88 | bool SubmitErrors;
89 | bool SubmitAverageFPS;
90 | bool SubmitCriticalFPS;
91 | bool InfoLogEditor;
92 | bool InfoLogBuild;
93 | bool VerboseLogBuild;
94 |
95 | PlatformInfo GetActivePlatform() const;
96 | };
97 |
98 | static FGameAnalyticsProjectSettings LoadProjectSettings();
99 |
100 | private:
101 |
102 | UGameAnalytics* GameAnalytics{nullptr};
103 |
104 | virtual void StartupModule() override;
105 | virtual void ShutdownModule() override;
106 |
107 | static FORCEINLINE FString GetIniName() { return FString::Printf(TEXT("%sDefaultEngine.ini"), *FPaths::SourceConfigDir()); }
108 | };
109 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/GameAnalyticsProvider.h:
--------------------------------------------------------------------------------
1 | // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "UObject/Package.h"
7 | #include "UObject/UObjectGlobals.h"
8 |
9 | #include "GameAnalytics.h"
10 | #include "GameAnalyticsModule.h"
11 |
12 | class FGameAnalyticsProvider :
13 | public IAnalyticsProvider
14 | {
15 | /** Path where analytics files are saved out */
16 | FString AnalyticsFilePath;
17 | /** Tracks whether we need to start the session or restart it */
18 | bool bHasSessionStarted;
19 | /** Whether an event was written before or not */
20 | bool bHasWrittenFirstEvent;
21 | /** Id representing the user the analytics are recording for */
22 | FString UserId;
23 | /** Unique Id representing the session the analytics are recording for */
24 | FString SessionId;
25 | /** Holds the Age if set */
26 | int32 Age;
27 |
28 | /** handles GA */
29 | UGameAnalytics* GameAnalytics;
30 |
31 | /** Settings for GameAnalytics, loaded from project configuration files */
32 | FGameAnalyticsModule::FGameAnalyticsProjectSettings ProjectSettings;
33 |
34 | FString GetAnalyticsPath() const;
35 | FString GenerateUserId() const;
36 |
37 | public:
38 |
39 | FGameAnalyticsProvider(UGameAnalytics* GameAnalytics);
40 | virtual ~FGameAnalyticsProvider();
41 |
42 | virtual bool StartSession(const TArray& Attributes) override;
43 | virtual void EndSession() override;
44 | virtual void FlushEvents() override;
45 |
46 | void OnQuit();
47 |
48 | virtual void SetDefaultEventAttributes(TArray&& Attributes) override;
49 | virtual TArray GetDefaultEventAttributesSafe() const override;
50 | virtual int32 GetDefaultEventAttributeCount() const override;
51 | virtual FAnalyticsEventAttribute GetDefaultEventAttribute(int AttributeIndex) const override;
52 |
53 | virtual void SetUserID(const FString& InUserID) override;
54 | virtual FString GetUserID() const override;
55 |
56 | virtual FString GetSessionID() const override;
57 | virtual bool SetSessionID(const FString& InSessionID) override;
58 |
59 | virtual void RecordEvent(const FString& EventName, const TArray& Attributes) override;
60 |
61 | virtual void SetGender(const FString& InGender) ;
62 | virtual void SetAge(const int32 InAge) ;
63 |
64 | virtual void RecordItemPurchase(const FString& ItemId, const FString& Currency, int PerItemCost, int ItemQuantity) override;
65 | virtual void RecordItemPurchase(const FString& ItemId, int ItemQuantity, const TArray& Attributes) override;
66 | virtual void RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount, const FString& RealCurrencyType, float RealMoneyCost, const FString& PaymentProvider) override;
67 | virtual void RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount) override;
68 | virtual void RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount, const TArray& Attributes) override;
69 | virtual void RecordCurrencyGiven(const FString& GameCurrencyType, int GameCurrencyAmount) override;
70 | virtual void RecordCurrencyGiven(const FString& GameCurrencyType, int GameCurrencyAmount, const TArray& Attributes) override;
71 | virtual void RecordError(const FString& Error) override;
72 | virtual void RecordError(const FString& Error, const TArray& Attributes) override;
73 | virtual void RecordProgress(const FString& ProgressType, const FString& ProgressHierarchy) override;
74 | virtual void RecordProgress(const FString& ProgressType, const FString& ProgressHierarchy, const TArray& Attributes) override;
75 | virtual void RecordProgress(const FString& ProgressType, const TArray& ProgressHierarchy, const TArray& Attributes) override;
76 | };
77 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GameAnalytics.Build.cs:
--------------------------------------------------------------------------------
1 | using UnrealBuildTool;
2 | using System.IO;
3 | using System;
4 |
5 |
6 | namespace UnrealBuildTool.Rules
7 | {
8 | public class GameAnalytics : ModuleRules
9 | {
10 | #if WITH_FORWARDED_MODULE_RULES_CTOR
11 | public GameAnalytics(ReadOnlyTargetRules Target) : base(Target)
12 | #else
13 | public GameAnalytics(TargetInfo Target)
14 | #endif
15 | {
16 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
17 |
18 | var ThirdPartyPath = Path.GetFullPath(Path.Combine(ModuleDirectory, "../ThirdParty/"));
19 | var GA_SDK_CppPath = Path.GetFullPath(Path.Combine(ThirdPartyPath, "GA-SDK-CPP", "lib"));
20 | var libPath = Path.Combine(ThirdPartyPath, "lib");
21 |
22 | if(Target.Platform == UnrealTargetPlatform.Win64)
23 | {
24 | PublicAdditionalLibraries.Add(Path.Combine(GA_SDK_CppPath, "Win64", "GameAnalytics.lib"));
25 | PrivateDependencyModuleNames.AddRange(new string[] { "OpenSSL", "libcurl", "nghttp2", "zlib" });
26 | PrivateIncludePaths.Add(Path.GetFullPath(Path.Combine(ModuleDirectory, "GA-SDK-CPP")));
27 | }
28 | else if(Target.Platform == UnrealTargetPlatform.Android)
29 | {
30 | PrivateDependencyModuleNames.Add("Launch");
31 | PrivateIncludePaths.Add(Path.Combine(ModuleDirectory, "Private/Android"));
32 | }
33 | else if(Target.Platform == UnrealTargetPlatform.Mac)
34 | {
35 | PublicAdditionalLibraries.Add(Path.Combine(GA_SDK_CppPath, "Mac", "libGameAnalytics.a"));
36 |
37 | PublicFrameworks.AddRange(
38 | new string[] {
39 | "CoreFoundation",
40 | "Foundation",
41 | "CoreServices",
42 | "SystemConfiguration",
43 | "Metal",
44 | "MetalKit"
45 | }
46 | );
47 | PrivateDependencyModuleNames.AddRange(new string[] { "OpenSSL", "libcurl", "nghttp2" });
48 |
49 | PrivateIncludePaths.Add(Path.GetFullPath(Path.Combine(ModuleDirectory, "GA-SDK-CPP")));
50 | }
51 | else if(Target.Platform == UnrealTargetPlatform.Linux)
52 | {
53 | PublicAdditionalLibraries.Add(Path.Combine(GA_SDK_CppPath, "Linux-clang", "libGameAnalytics.a"));
54 | PrivateDependencyModuleNames.AddRange(new string[] { "OpenSSL", "libcurl", "nghttp2" });
55 | PrivateIncludePaths.Add(Path.GetFullPath(Path.Combine(ModuleDirectory, "GA-SDK-CPP")));
56 | }
57 | else if(Target.Platform == UnrealTargetPlatform.IOS)
58 | {
59 | PublicAdditionalLibraries.Add(Path.Combine(libPath, "ios", "libGameAnalytics.a"));
60 | PrivateIncludePaths.Add(Path.Combine(ModuleDirectory, "Private/IOS"));
61 | PublicFrameworks.AddRange(
62 | new string[] {
63 | "AdSupport",
64 | "SystemConfiguration",
65 | "AppTrackingTransparency"
66 | }
67 | );
68 |
69 | PublicAdditionalLibraries.AddRange(
70 | new string[] {
71 | "sqlite3",
72 | "z",
73 | "c++"
74 | });
75 |
76 | string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
77 | AdditionalPropertiesForReceipt.Add("IOSPlugin", Path.Combine(PluginPath, "GameAnalytics_iOS_UPL.xml"));
78 | }
79 | /*else if(Target.Platform == UnrealTargetPlatform.HTML5)
80 | {
81 | if (Target.Architecture != "-win32")
82 | {
83 | PublicAdditionalLibraries.Add(Path.Combine(libPath, "html5", "GameAnalytics.jspre"));
84 | PublicAdditionalLibraries.Add(Path.Combine(libPath, "html5", "GameAnalyticsUnreal.js"));
85 | }
86 | }*/
87 | else
88 | {
89 | throw new NotImplementedException("This target platform is not configured for GameAnalytics SDK: " + Target.Platform.ToString());
90 | }
91 |
92 | PublicDependencyModuleNames.AddRange(
93 | new string[]
94 | {
95 | "Core",
96 | "CoreUObject",
97 | "Engine",
98 | "Json"
99 | // ... add other public dependencies that you statically link with here ...
100 | }
101 | );
102 |
103 | PrivateIncludePaths.Add(Path.GetFullPath(Path.Combine(ModuleDirectory, "Private")));
104 | PrivateIncludePaths.Add(Path.GetFullPath(Path.Combine(ModuleDirectory, "Public")));
105 | PublicIncludePaths.Add(Path.GetFullPath(Path.Combine(ModuleDirectory, "Public")));
106 |
107 |
108 | PrivateDependencyModuleNames.AddRange(
109 | new string[]
110 | {
111 | "Analytics",
112 | "Engine",
113 | "Json"
114 | }
115 | );
116 |
117 | PublicIncludePathModuleNames.AddRange(
118 | new string[]
119 | {
120 | "Analytics",
121 | "Engine",
122 | "Json"
123 | }
124 | );
125 |
126 | if (Target.Platform == UnrealTargetPlatform.Android)
127 | {
128 | string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
129 | AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(PluginPath, "GameAnalytics_APL.xml"));
130 | }
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GA-SDK-UNREAL
2 | GameAnalytics SDK for the Unreal Engine.
3 |
4 | Documentation can be found [here](https://docs.gameanalytics.com/integrations/sdk/unreal).
5 |
6 | If you have any issues or feedback regarding the SDK, please contact our friendly support team [here](https://gameanalytics.com/contact).
7 |
8 | > :information_source:
9 | >
10 | > The Unreal SDK include support for **iOS**, **Android**, **HTML5**, **Windows**, **Linux** and **Mac** platforms
11 | >
12 | > Requirements:
13 | > * **Unreal Engine:** 5.3+
14 | > * **iOS:** iOS 10+
15 | > * **Android:** Android API Level 21
16 | > * **Windows:** Minimum specs for UE5
17 | > * **Mac:** Minimum specs for UE5
18 |
19 | ## Usage
20 |
21 | ## C++ Code
22 |
23 | There are two ways of using the GameAnalytics plugin inside your C++ code:
24 |
25 | - directly using an instance of an `UGameAnalytics` object
26 | - using the `IAnalyticsProvider` interface
27 |
28 | The former will provide all the plugin features, including remote configurations and performance tracking. The `IAnalyticsProvider` will provide an easier integration inside Unreal, but will only expose limited features.
29 |
30 | Due to the inner workings of the module the `IAnalyticsProvider` will retrieve its settings from `Project Settings -> Plugins -> GameAnalytics`. While using `UGameAnalytics` directly will require you to manually call the setup functions (either from C++ or Blueprints).
31 |
32 | If you are using the `IAnalyticsInterface`, but desire to enable advanced features of the SDK, you can safely mix calls from both `IAnalyticsInterface` and `UGameAnalytics` as both are using the same instance inside the module (provided you initialize the SDK only once).
33 |
34 | ### Initialization
35 |
36 | The `UGameAnalytics` class provides all plugin functionality. The GameAnalytics module will hold an instance of `UGameAnalytics*`.
37 |
38 | Add the headers to your project:
39 |
40 | ```c++
41 | #include "GameAnalytics.h"
42 | #include "GameAnalyticsModule.h"
43 | ```
44 |
45 | Setup and initialize the SDK:
46 |
47 | ```c++
48 | UGameAnalytics* GameAnalytics = FGameAnalyticsModule::Get().GetInstance();
49 |
50 | // enable extra info logging
51 | GameAnalytics->SetEnabledInfoLog(true);
52 |
53 | // enable verbose logging -> don't forget to turn off in shipping builds
54 | GameAnalytics->SetEnabledVerboseLog(true);
55 |
56 | // configure available resources
57 | GameAnalytics->ConfigureAvailableResourceItemTypes({ TEXT("copper"), TEXT("silver"), TEXT("gold") });
58 |
59 | // initialize the SDK with your keys
60 | GameAnalytics->Initialize(GAME_KEY, SECRET_KEY);
61 | ```
62 |
63 | ### Sending Events
64 |
65 | After the SDK initialization you can start sending events
66 |
67 | ```c++
68 | // send a design event
69 | GameAnalytics->AddDesignEventWithValue(TEXT("kill:dragon"), 100);
70 |
71 | // send a progression event
72 | GameAnalytics->AddProgressionEvent(EGAProgressionStatus::complete, TEXT("swamplands"), TEXT("temple"), TEXT("level_0"));
73 |
74 | // send a resource event
75 | GameAnalytics->AddResourceEvent(EGAResourceFlowType::source, TEXT("gold"), 200, TEXT("gold_pack"), TEXT("gold_pack_large"));
76 |
77 | // add a business event, amount needs to be in the smallest currency denominiation! (this means for USD you need to send the amount in cents)
78 | GameAnalytics->AddBusinessEvent(TEXT("USD"), 1000, TEXT("premium_gold_bundle"), TEXT("gold_pack_5000"), TEXT("end_level_shop"));
79 |
80 | // send an error event
81 | GameAnalytics->AddErrorEvent(EGAErrorSeverity::warning, TEXT("error message"));
82 |
83 | ```
84 |
85 | ### Using Custom Fields
86 |
87 | You can attach up to 50 custom fields to any event.
88 |
89 | The following types are supported:
90 |
91 | - boolean
92 | - number (64-bit floating point)
93 | - string
94 |
95 | ```c++
96 | FGACustomFields Fields;
97 |
98 | Fields.Set(TEXT("my_bool"), true);
99 | Fields.Set(TEXT("my_number"), 1000.f);
100 | fields.Set(TEXT("my_string"), FString(TEXT("halloween_event")));
101 |
102 | GameAnalytics->AddDesignEventWithValue(TEXT("MyEvent"), 200, fields);
103 | ```
104 |
105 | ### Performance Tracker
106 |
107 | Before initialization (e.g: calling `UGameAnlalytics::Initialize`), you can setup optional performance reporting.
108 |
109 | ```c++
110 | // track boot-time
111 | GameAnalytics->EnableSDKInitEvent(true);
112 |
113 | // track hardware information (e.g: cpu name, gpu name, number of cores, memory etc)
114 | GameAnalytics->EnableHealthHardwareInfo(true);
115 |
116 | // track FPS
117 | GameAnalytics->EnableFpsHistogram(true);
118 |
119 | // track memory usage
120 | GameAnalytics->EnableMemoryHistogram(true);
121 | ```
122 |
123 | ### Using IAnalyticsProvider
124 |
125 | GameAnalytics also proivdes a `IAnalyticsProvider` implementation for seamless integration inside the Unreal ecosystem.
126 |
127 | The `IAnalyticsProvider` interface will retrieve its configuration from `Project Settings -> Plugins -> GameAnalytics` (e.g: game keys, resources, info/verbose log).
128 |
129 | ```c++
130 |
131 | TSharedPtr AnalyticsProvider = FGameAnalyticsModule::Get().CreateAnalyticsProvider(FGameAnalyticsModule::Delegate());
132 |
133 | // start session will invoke UGameAnalytics::Initialize on first call
134 | AnalyticsProvider->StartSession();
135 |
136 | // equivalent to GameAnalytics->AddDesginEvent(TEXT("my:level:id"))
137 | AnalyticsProvider->RecordEvent(TEXT("my:level:id"), MakeAnalyticsEventAttributeArray(TEXT("value"), 100.0));
138 |
139 | // equivalent to GameAnalytics->AddErrorEvent(EGAErrorSeverity::warning, TEXT("error message"));
140 | AnalyticsProvider->RecordError(TEXT("error message"), MakeAnalyticsEventAttributeArray(TEXT("severity"), TEXT("warning")));
141 |
142 | // equivalent to GameAnalytics->AddProgressionEventWithScore(EGAProgressionStatus::complete, 100, TEXT("progression1"), TEXT("progression2"), TEXT("progression3"))
143 | AnalyticsProvider->RecordProgress(TEXT("complete"), {TEXT("progression1"), TEXT("progression2"), TEXT("progression3")}, MakeAnalyticsEventAttributeArray(TEXT("value"), 100));
144 | ```
145 |
146 | ## Blueprints
147 |
148 | All public functions from `UGameAnalytics` are also exposed to blueprints, as well as the `IAnalyticsProvider` implementation. Anything that can be done via code is also possible using only blueprints.
149 |
150 | Example initialization from blueprint:
151 | 
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/Desktop/GAWrapperCpp.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "GAWrapper.h"
4 |
5 | namespace gameanalytics
6 | {
7 | class GAWrapperCpp:
8 | public GAWrapper
9 | {
10 | virtual void SetAvailableCustomDimensions01(std::vector const& list) override;
11 | virtual void SetAvailableCustomDimensions02(std::vector const& list) override;
12 | virtual void SetAvailableCustomDimensions03(std::vector const& list) override;
13 |
14 | virtual void SetAvailableResourceCurrencies(std::vector const& list) override;
15 | virtual void SetAvailableResourceItemTypes(std::vector const& list) override;
16 |
17 | virtual void SetSDKVersion(std::string const& version) override;
18 |
19 | virtual void SetGameEngineVersion(std::string const& version) override;
20 |
21 | virtual void SetBuild(std::string const& build) override;
22 | virtual void SetCustomUserId(std::string const& userId) override;
23 | virtual void SetExternalUserId(std::string const& extUserId) override;
24 |
25 | virtual std::string GetUserId() override;
26 | virtual std::string GetExternalUserId() override;
27 |
28 | virtual void SetAutoDetectAppVersion(bool flag) override;
29 |
30 | virtual void Initialize(std::string const& gamekey, std::string const& gamesecret) override;
31 |
32 | virtual void SetCustomDimension01(std::string const& customDimension) override;
33 | virtual void SetCustomDimension02(std::string const& customDimension) override;
34 | virtual void SetCustomDimension03(std::string const& customDimension) override;
35 |
36 | virtual void SetGlobalCustomEventFields(std::string const& customFields) override;
37 | virtual void SetEnabledManualSessionHandling (bool enabled) override;
38 | virtual void SetEnabledEventSubmission(bool enabled, bool doCacheLocally = false) override;
39 |
40 | virtual void SetEnabledErrorReporting(bool flag) override;
41 |
42 | virtual void StartSession() override;
43 | virtual void EndSession() override;
44 |
45 | virtual void AddBusinessEvent(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const&cartType, std::string const& receipt, std::string const& fields, bool mergeFields) override;
46 | virtual void AddBusinessEventAndAutoFetchReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& fields, bool mergeFields) override;
47 | virtual void AddBusinessEventWithReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& receipt, std::string const& store, std::string const& signature, std::string const& fields, bool mergeFields) override;
48 |
49 | virtual void AddResourceEvent(EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& fields, bool mergeFields) override;
50 |
51 | virtual void AddProgressionEvent(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, std::string const& fields, bool mergeFields) override;
52 | virtual void AddProgressionEventWithScore(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, std::string const& fields, bool mergeFields) override;
53 |
54 | virtual void AddDesignEvent(std::string const& eventID, std::string const& fields, bool mergeFields) override;
55 | virtual void AddDesignEventWithValue(std::string const& eventId, float value, std::string const& fields, bool mergeFields) override;
56 |
57 | virtual void AddErrorEvent(EGAErrorSeverity severity, std::string const& message, std::string const& fields, bool mergeFields) override;
58 |
59 | virtual void AddAdEventWithDuration(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, int64_t duration, std::string const& fields, bool mergeFields) override;
60 | virtual void AddAdEventWithReason(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, EGAAdError noAdReason, std::string const& fields, bool mergeFields) override;
61 | virtual void AddAdEvent(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, std::string const& fields, bool mergeFields) override;
62 |
63 | virtual void SetInfoLog (bool enabled) override;
64 | virtual void SetVerboseLog (bool enabled) override;
65 |
66 | // ----------------------- REMOTE CONFIGS ---------------------- //
67 | virtual std::string GetRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue) override;
68 |
69 | virtual double GetRemoteConfigsValueAsNumber(std::string const& key, double defaultValue) override;
70 |
71 | virtual std::string GetRemoteConfigsValueAsJson(std::string const& key) override;
72 |
73 | virtual bool IsRemoteConfigsReady() override;
74 |
75 | virtual std::string GetRemoteConfigsContentAsString() override;
76 |
77 | virtual std::string GetABTestingId() override;
78 |
79 | virtual std::string GetABTestingVariantId() override;
80 |
81 | /////////////////// HEALTH /////////////////////////
82 |
83 | virtual void EnableSDKInitEvent(bool flag) override;
84 |
85 | virtual void EnableFpsHistogram(FPSTracker tracker, bool flag) override;
86 |
87 | virtual void EnableMemoryHistogram(bool flag) override;
88 |
89 | virtual void EnableHealthHardwareInfo(bool flag) override;
90 |
91 | //////////////////////////////////////////////////
92 |
93 | virtual int64_t GetElapsedSessionTime() override;
94 |
95 | virtual int64_t GetElapsedTimeForPreviousSession() override;
96 |
97 | virtual int64_t GetElapsedTimeFromAllSessions() override;
98 |
99 | //////////////////////////////////////////////////
100 |
101 | virtual void EnableAdvertisingId(bool enabled) override;
102 |
103 | /////
104 |
105 | virtual void OnQuit() override;
106 |
107 | virtual void SetWritablePath(std::string const& path) override;
108 |
109 | };
110 | }
111 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Public/GAWrapper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "GAEnums.h"
9 |
10 | namespace gameanalytics
11 | {
12 | using FPSTracker = std::function;
13 |
14 | class GAWrapper
15 | {
16 | public:
17 |
18 | virtual ~GAWrapper() {};
19 |
20 | virtual void SetAvailableCustomDimensions01(std::vector const& list) = 0;
21 | virtual void SetAvailableCustomDimensions02(std::vector const& list) = 0;
22 | virtual void SetAvailableCustomDimensions03(std::vector const& list) = 0;
23 |
24 | virtual void SetAvailableResourceCurrencies(std::vector const& list) = 0;
25 | virtual void SetAvailableResourceItemTypes(std::vector const& list) = 0;
26 |
27 | virtual void SetSDKVersion(std::string const& version) = 0;
28 |
29 | virtual void SetGameEngineVersion(std::string const& version) = 0;
30 |
31 | virtual void SetBuild(std::string const& build) = 0;
32 | virtual void SetCustomUserId(std::string const& userId) = 0;
33 | virtual void SetExternalUserId(std::string const& extUserId) = 0;
34 |
35 | virtual std::string GetUserId() = 0;
36 | virtual std::string GetExternalUserId() = 0;
37 |
38 | virtual void SetAutoDetectAppVersion(bool flag) = 0;
39 |
40 | virtual void Initialize(std::string const& gamekey, std::string const& gamesecret) = 0;
41 |
42 | virtual void SetCustomDimension01(std::string const& customDimension) = 0;
43 | virtual void SetCustomDimension02(std::string const& customDimension) = 0;
44 | virtual void SetCustomDimension03(std::string const& customDimension) = 0;
45 |
46 | virtual void SetGlobalCustomEventFields(std::string const& customFields) = 0;
47 | virtual void SetEnabledManualSessionHandling (bool enabled) = 0;
48 |
49 | virtual void SetEnabledEventSubmission(bool enabled, bool doCache) = 0;
50 | virtual void SetEnabledErrorReporting(bool flag) = 0;
51 |
52 | virtual void StartSession() = 0;
53 | virtual void EndSession() = 0;
54 |
55 | virtual void AddBusinessEvent(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const&cartType, std::string const& receipt, std::string const& fields, bool mergeFields) = 0;
56 | virtual void AddBusinessEventAndAutoFetchReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& fields, bool mergeFields) = 0;
57 | virtual void AddBusinessEventWithReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& receipt, std::string const& store, std::string const& signature, std::string const& fields, bool mergeFields) = 0;
58 |
59 | virtual void AddResourceEvent(EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& fields, bool mergeFields) = 0;
60 |
61 | virtual void AddProgressionEvent(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, std::string const& fields, bool mergeFields) = 0;
62 | virtual void AddProgressionEventWithScore(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, std::string const& fields, bool mergeFields) = 0;
63 |
64 | virtual void AddDesignEvent(std::string const& eventID, std::string const& fields, bool mergeFields) = 0;
65 | virtual void AddDesignEventWithValue(std::string const& eventId, float value, std::string const& fields, bool mergeFields) = 0;
66 |
67 | virtual void AddErrorEvent(EGAErrorSeverity severity, std::string const& message, std::string const& fields, bool mergeFields) = 0;
68 |
69 | virtual void AddAdEventWithDuration(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, int64_t duration, std::string const& fields, bool mergeFields) = 0;
70 | virtual void AddAdEventWithReason(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, EGAAdError noAdReason, std::string const& fields, bool mergeFields) = 0;
71 | virtual void AddAdEvent(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, std::string const& fields, bool mergeFields) = 0;
72 |
73 | virtual void SetInfoLog (bool enabled) = 0;
74 | virtual void SetVerboseLog (bool enabled) = 0;
75 |
76 | // ----------------------- REMOTE CONFIGS ---------------------- //
77 | virtual std::string GetRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue) = 0;
78 |
79 | virtual double GetRemoteConfigsValueAsNumber(std::string const& key, double defaultValue) = 0;
80 |
81 | virtual std::string GetRemoteConfigsValueAsJson(std::string const& key) = 0;
82 |
83 | virtual bool IsRemoteConfigsReady() = 0;
84 |
85 | virtual std::string GetRemoteConfigsContentAsString() = 0;
86 |
87 | virtual std::string GetABTestingId() = 0;
88 |
89 | virtual std::string GetABTestingVariantId() = 0;
90 |
91 | /////////////////// HEALTH /////////////////////////
92 |
93 | virtual void EnableSDKInitEvent(bool flag) = 0;
94 |
95 | virtual void EnableFpsHistogram(FPSTracker tracker, bool flag) = 0;
96 |
97 | virtual void EnableMemoryHistogram(bool flag) = 0;
98 |
99 | virtual void EnableHealthHardwareInfo(bool flag) = 0;
100 |
101 | //////////////////////////////////////////////////
102 |
103 | virtual int64_t GetElapsedSessionTime() = 0;
104 |
105 | virtual int64_t GetElapsedTimeForPreviousSession() = 0;
106 |
107 | virtual int64_t GetElapsedTimeFromAllSessions() = 0;
108 |
109 | //////////////////////////////////////////////////
110 |
111 | virtual void EnableAdvertisingId(bool enabled) = 0;
112 |
113 | /////
114 |
115 | virtual void OnQuit() = 0;
116 |
117 | virtual void SetWritablePath(std::string const& path) = 0;
118 | };
119 | }
120 |
121 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/IOS/GAWrapperIOS.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "GAWrapper.h"
4 |
5 | namespace gameanalytics
6 | {
7 | class GAWrapperIOS:
8 | public GAWrapper
9 | {
10 | public:
11 |
12 | virtual void SetAvailableCustomDimensions01(std::vector const& list) override;
13 | virtual void SetAvailableCustomDimensions02(std::vector const& list) override;
14 | virtual void SetAvailableCustomDimensions03(std::vector const& list) override;
15 |
16 | virtual void SetAvailableResourceCurrencies(std::vector const& list) override;
17 | virtual void SetAvailableResourceItemTypes(std::vector const& list) override;
18 |
19 | virtual void SetSDKVersion(std::string const& version) override;
20 |
21 | virtual void SetGameEngineVersion(std::string const& version) override;
22 |
23 | virtual void SetBuild(std::string const& build) override;
24 | virtual void SetCustomUserId(std::string const& userId) override;
25 | virtual void SetExternalUserId(std::string const& extUserId) override;
26 |
27 | virtual std::string GetUserId() override;
28 | virtual std::string GetExternalUserId() override;
29 |
30 | virtual void SetAutoDetectAppVersion(bool flag) override;
31 |
32 | virtual void Initialize(std::string const& gamekey, std::string const& gamesecret) override;
33 |
34 | virtual void SetCustomDimension01(std::string const& customDimension) override;
35 | virtual void SetCustomDimension02(std::string const& customDimension) override;
36 | virtual void SetCustomDimension03(std::string const& customDimension) override;
37 |
38 | virtual void SetGlobalCustomEventFields(std::string const& customFields) override;
39 | virtual void SetEnabledManualSessionHandling(bool enabled) override;
40 | virtual void SetEnabledEventSubmission(bool enable, bool offlineCaching = true) override;
41 | virtual void SetEnabledErrorReporting(bool flag) override;
42 |
43 | virtual void StartSession() override;
44 | virtual void EndSession() override;
45 |
46 | virtual void AddBusinessEvent(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const&cartType, std::string const& receipt, std::string const& fields, bool mergeFields) override;
47 | virtual void AddBusinessEventAndAutoFetchReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& fields, bool mergeFields) override;
48 | virtual void AddBusinessEventWithReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& receipt, std::string const& store, std::string const& signature, std::string const& fields, bool mergeFields) override;
49 |
50 | virtual void AddResourceEvent(EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& fields, bool mergeFields) override;
51 |
52 | virtual void AddProgressionEvent(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, std::string const& fields, bool mergeFields) override;
53 | virtual void AddProgressionEventWithScore(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, std::string const& fields, bool mergeFields) override;
54 |
55 | virtual void AddDesignEvent(std::string const& eventID, std::string const& fields, bool mergeFields) override;
56 | virtual void AddDesignEventWithValue(std::string const& eventId, float value, std::string const& fields, bool mergeFields) override;
57 |
58 | virtual void AddErrorEvent(EGAErrorSeverity severity, std::string const& message, std::string const& fields, bool mergeFields) override;
59 |
60 | virtual void AddAdEventWithDuration(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, int64_t duration, std::string const& fields, bool mergeFields) override;
61 | virtual void AddAdEventWithReason(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, EGAAdError noAdReason, std::string const& fields, bool mergeFields) override;
62 | virtual void AddAdEvent(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, std::string const& fields, bool mergeFields) override;
63 |
64 | virtual void SetInfoLog(bool enabled) override;
65 | virtual void SetVerboseLog(bool enabled) override;
66 |
67 |
68 | // ----------------------- REMOTE CONFIGS ---------------------- //
69 |
70 | virtual std::string GetRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue) override;
71 |
72 | virtual std::string GetRemoteConfigsValueAsJson(std::string const& key) override;
73 |
74 | virtual double GetRemoteConfigsValueAsNumber(std::string const& key, double defaultValue) override;
75 |
76 | virtual bool IsRemoteConfigsReady() override;
77 |
78 | virtual std::string GetRemoteConfigsContentAsString() override;
79 |
80 | virtual std::string GetABTestingId() override;
81 |
82 | virtual std::string GetABTestingVariantId() override;
83 |
84 | ///// HEALTH
85 |
86 | virtual void EnableSDKInitEvent(bool flag) override;
87 |
88 | virtual void EnableFpsHistogram(FPSTracker tracker, bool flag) override;
89 |
90 | virtual void EnableMemoryHistogram(bool flag) override;
91 |
92 | virtual void EnableHealthHardwareInfo(bool flag) override;
93 |
94 | /////////////////////////////////////////////////////////////
95 |
96 | virtual int64_t GetElapsedSessionTime() override;
97 |
98 | virtual int64_t GetElapsedTimeForPreviousSession() override;
99 |
100 | virtual int64_t GetElapsedTimeFromAllSessions() override;
101 |
102 | ////////////////////////////////////////////////////////
103 |
104 | virtual void EnableAdvertisingId(bool value) override;
105 |
106 | virtual void OnQuit() override;
107 |
108 | virtual void SetWritablePath(std::string const& path) override;
109 |
110 | };
111 | }
112 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalyticsEditor/Private/GameAnalyticsTargetSettingsCustomization.h:
--------------------------------------------------------------------------------
1 | // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "Widgets/Input/SComboBox.h"
7 | #include "PropertyEditorModule.h"
8 | #include "GameAnalyticsProjectSettings.h"
9 | #include "IDetailCustomization.h"
10 |
11 | #include "Http.h"
12 |
13 | //////////////////////////////////////////////////////////////////////////
14 | // FAndroidTargetSettingsCustomization
15 |
16 | class FGameAnalyticsTargetSettingsCustomization : public IDetailCustomization
17 | {
18 | public:
19 |
20 | struct GAME {
21 | FString Name;
22 | int Id;
23 | FString GameKey;
24 | FString SecretKey;
25 | };
26 |
27 | struct STUDIO {
28 | FString Name;
29 | int Id;
30 | int OrganizationId;
31 | TArray Games;
32 |
33 | /*STUDIO (FString aName, int aId, TArray aGames) :
34 | Name(aName), Id(aId), Games(aGames)
35 | {
36 | }*/
37 | };
38 |
39 | struct ORGANIZATION {
40 | FString Name;
41 | int Id;
42 | TArray Studios;
43 | };
44 |
45 | // Makes a new instance of this detail layout class for a specific detail view requesting it
46 | static TSharedRef MakeInstance();
47 |
48 | // IDetailCustomization interface
49 | virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override;
50 | // End of IDetailCustomization interface
51 |
52 | void UsernameEntered(const FText& NewText, ETextCommit::Type CommitInfo);
53 | void UsernameChanged(const FText& NewText);
54 |
55 | void PasswordEntered(const FText& NewText, ETextCommit::Type CommitInfo);
56 | void PasswordChanged(const FText& NewText);
57 |
58 | void FillOrganizationsString(TArray OrganizationList);
59 | TSharedRef HandleStudiosComboBoxGenerateWidget(TSharedPtr StringItem);
60 | void HandleStudiosComboBoxSelectionChanged(TSharedPtr StringItem, ESelectInfo::Type SelectInfo);
61 | FText HandleStudiosComboBoxContentText() const;
62 |
63 | void OpenStudioAndGameSelector();
64 |
65 | void OnOrganizationMenuItemClickedIos(FGameAnalyticsTargetSettingsCustomization::ORGANIZATION OrganizationItem) const;
66 | void OnStudioMenuItemClickedIos(FGameAnalyticsTargetSettingsCustomization::STUDIO StudioItem) const;
67 | void OnGameMenuItemClickedIos(FGameAnalyticsTargetSettingsCustomization::GAME GameItem) const;
68 | void OnOrganizationMenuItemClickedAndroid(FGameAnalyticsTargetSettingsCustomization::ORGANIZATION OrganizationItem) const;
69 | void OnStudioMenuItemClickedAndroid(FGameAnalyticsTargetSettingsCustomization::STUDIO StudioItem) const;
70 | void OnGameMenuItemClickedAndroid(FGameAnalyticsTargetSettingsCustomization::GAME GameItem) const;
71 | void OnOrganizationMenuItemClickedMac(FGameAnalyticsTargetSettingsCustomization::ORGANIZATION OrganizationItem) const;
72 | void OnStudioMenuItemClickedMac(FGameAnalyticsTargetSettingsCustomization::STUDIO StudioItem) const;
73 | void OnGameMenuItemClickedMac(FGameAnalyticsTargetSettingsCustomization::GAME GameItem) const;
74 | void OnOrganizationMenuItemClickedWindows(FGameAnalyticsTargetSettingsCustomization::ORGANIZATION OrganizationItem) const;
75 | void OnStudioMenuItemClickedWindows(FGameAnalyticsTargetSettingsCustomization::STUDIO StudioItem) const;
76 | void OnGameMenuItemClickedWindows(FGameAnalyticsTargetSettingsCustomization::GAME GameItem) const;
77 | void OnOrganizationMenuItemClickedLinux(FGameAnalyticsTargetSettingsCustomization::ORGANIZATION OrganizationItem) const;
78 | void OnStudioMenuItemClickedLinux(FGameAnalyticsTargetSettingsCustomization::STUDIO StudioItem) const;
79 | void OnGameMenuItemClickedLinux(FGameAnalyticsTargetSettingsCustomization::GAME GameItem) const;
80 | void OnOrganizationMenuItemClickedHtml5(FGameAnalyticsTargetSettingsCustomization::ORGANIZATION OrganizationItem) const;
81 | void OnStudioMenuItemClickedHtml5(FGameAnalyticsTargetSettingsCustomization::STUDIO StudioItem) const;
82 | void OnGameMenuItemClickedHtml5(FGameAnalyticsTargetSettingsCustomization::GAME GameItem) const;
83 |
84 | public:
85 | static FGameAnalyticsTargetSettingsCustomization& getInstance()
86 | {
87 | static FGameAnalyticsTargetSettingsCustomization instance; // Guaranteed to be destroyed.
88 | // Instantiated on first use.
89 | return instance;
90 | }
91 |
92 | TArray Organizations;
93 | ORGANIZATION SelectedOrganizationIos;
94 | STUDIO SelectedStudioIos;
95 | GAME SelectedGameIos;
96 | ORGANIZATION SelectedOrganizationAndroid;
97 | STUDIO SelectedStudioAndroid;
98 | GAME SelectedGameAndroid;
99 | ORGANIZATION SelectedOrganizationMac;
100 | STUDIO SelectedStudioMac;
101 | GAME SelectedGameMac;
102 | ORGANIZATION SelectedOrganizationWindows;
103 | STUDIO SelectedStudioWindows;
104 | GAME SelectedGameWindows;
105 | ORGANIZATION SelectedOrganizationLinux;
106 | STUDIO SelectedStudioLinux;
107 | GAME SelectedGameLinux;
108 | ORGANIZATION SelectedOrganizationHtml5;
109 | STUDIO SelectedStudioHtml5;
110 | GAME SelectedGameHtml5;
111 |
112 | private:
113 | FGameAnalyticsTargetSettingsCustomization() {};
114 |
115 | FGameAnalyticsTargetSettingsCustomization(FGameAnalyticsTargetSettingsCustomization const&) = delete;
116 | void operator=(FGameAnalyticsTargetSettingsCustomization const&) = delete;
117 |
118 | FReply OpenSetupWizard();
119 | FReply Login();
120 | TSharedRef UpdateOrganizationsIos() const;
121 | TSharedRef UpdateStudiosIos() const;
122 | TSharedRef UpdateGamesIos() const;
123 | TSharedRef UpdateOrganizationsAndroid() const;
124 | TSharedRef UpdateStudiosAndroid() const;
125 | TSharedRef UpdateGamesAndroid() const;
126 | TSharedRef UpdateOrganizationsMac() const;
127 | TSharedRef UpdateStudiosMac() const;
128 | TSharedRef UpdateGamesMac() const;
129 | TSharedRef UpdateOrganizationsWindows() const;
130 | TSharedRef UpdateStudiosWindows() const;
131 | TSharedRef UpdateGamesWindows() const;
132 | TSharedRef UpdateOrganizationsLinux() const;
133 | TSharedRef UpdateStudiosLinux() const;
134 | TSharedRef UpdateGamesLinux() const;
135 | TSharedRef UpdateOrganizationsHtml5() const;
136 | TSharedRef UpdateStudiosHtml5() const;
137 | TSharedRef UpdateGamesHtml5() const;
138 |
139 | FORCEINLINE FString GetIniName() const { return FString::Printf(TEXT("%sDefaultEngine.ini"), *FPaths::SourceConfigDir()); }
140 |
141 | private:
142 | IDetailLayoutBuilder* SavedLayoutBuilder;
143 |
144 | FHttpModule* Http;
145 | bool bIsBusy;
146 |
147 | FName Username;
148 | FName Password;
149 |
150 | TSharedPtr >> StudiosComboBox;
151 | TArray< TSharedPtr > StudiosComboBoxString;
152 | };
153 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/Android/GAWrapperAndroid.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #include "GAWrapper.h"
6 |
7 | namespace gameanalytics
8 | {
9 | class GAWrapperAndroid:
10 | public GAWrapper
11 | {
12 | std::string CallStringMethod(std::string const& name);
13 | std::string ConvertJString(jstring str);
14 |
15 | virtual JNIEnv* GetJavaEnv();
16 | virtual jclass GetGameAnalyticsClass();
17 |
18 | public:
19 |
20 | GAWrapperAndroid();
21 | virtual ~GAWrapperAndroid();
22 |
23 | virtual void SetAvailableCustomDimensions01(std::vector const& list) override;
24 | virtual void SetAvailableCustomDimensions02(std::vector const& list) override;
25 | virtual void SetAvailableCustomDimensions03(std::vector const& list) override;
26 |
27 | virtual void SetAvailableResourceCurrencies(std::vector const& list) override;
28 | virtual void SetAvailableResourceItemTypes(std::vector const& list) override;
29 |
30 | virtual void SetSDKVersion(std::string const& version) override;
31 | virtual void SetGameEngineVersion(std::string const& version) override;
32 |
33 | virtual void SetBuild(std::string const& build) override;
34 | virtual void SetCustomUserId(std::string const& userId) override;
35 | virtual void SetExternalUserId(std::string const& extUserId) override;
36 |
37 | virtual std::string GetUserId() override;
38 | virtual std::string GetExternalUserId() override;
39 |
40 | virtual void SetAutoDetectAppVersion(bool flag) override;
41 |
42 | virtual void Initialize(std::string const& gamekey, std::string const& gamesecret) override;
43 |
44 | virtual void SetCustomDimension01(std::string const& customDimension) override;
45 | virtual void SetCustomDimension02(std::string const& customDimension) override;
46 | virtual void SetCustomDimension03(std::string const& customDimension) override;
47 |
48 | virtual void SetGlobalCustomEventFields(std::string const& customFields) override;
49 | virtual void SetEnabledManualSessionHandling (bool enabled) override;
50 | virtual void SetEnabledEventSubmission(bool enabled, bool doCacheLocally = false) override;
51 |
52 | virtual void StartSession() override;
53 | virtual void EndSession() override;
54 |
55 | virtual void AddBusinessEvent(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const&cartType, std::string const& receipt, std::string const& fields, bool mergeFields) override;
56 | virtual void AddBusinessEventAndAutoFetchReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& fields, bool mergeFields) override;
57 | virtual void AddBusinessEventWithReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& receipt, std::string const& store, std::string const& signature, std::string const& fields, bool mergeFields) override;
58 |
59 | virtual void AddResourceEvent(EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& fields, bool mergeFields) override;
60 |
61 | virtual void AddProgressionEvent(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, std::string const& fields, bool mergeFields) override;
62 | virtual void AddProgressionEventWithScore(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, std::string const& fields, bool mergeFields) override;
63 |
64 | virtual void AddDesignEvent(std::string const& eventID, std::string const& fields, bool mergeFields) override;
65 | virtual void AddDesignEventWithValue(std::string const& eventId, float value, std::string const& fields, bool mergeFields) override;
66 |
67 | virtual void AddErrorEvent(EGAErrorSeverity severity, std::string const& message, std::string const& fields, bool mergeFields) override;
68 |
69 | virtual void AddAdEventWithDuration(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, int64_t duration, std::string const& fields, bool mergeFields) override;
70 | virtual void AddAdEventWithReason(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, EGAAdError noAdReason, std::string const& fields, bool mergeFields) override;
71 | virtual void AddAdEvent(EGAAdAction adAction, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, std::string const& fields, bool mergeFields) override;
72 |
73 | virtual void SetInfoLog(bool enabled) override;
74 |
75 | virtual void SetVerboseLog(bool enabled) override;
76 |
77 | virtual void SetEnabledErrorReporting(bool flag) override;
78 |
79 | // ----------------------- REMOTE CONFIGS ---------------------- //
80 | virtual std::string GetRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue) override;
81 |
82 | virtual double GetRemoteConfigsValueAsNumber(std::string const& key, double defaultValue) override;
83 |
84 | virtual std::string GetRemoteConfigsValueAsJson(std::string const& key) override;
85 |
86 | virtual bool IsRemoteConfigsReady() override;
87 |
88 | virtual std::string GetRemoteConfigsContentAsString() override;
89 |
90 | virtual std::string GetABTestingId() override;
91 |
92 | virtual std::string GetABTestingVariantId() override;
93 |
94 | ///// HEALTH
95 |
96 | virtual void EnableSDKInitEvent(bool flag) override;
97 |
98 | virtual void EnableFpsHistogram(FPSTracker tracker, bool flag) override;
99 |
100 | virtual void EnableMemoryHistogram(bool flag) override;
101 |
102 | virtual void EnableHealthHardwareInfo(bool flag) override;
103 |
104 | ////////////////////////////////////////////////////////
105 |
106 | virtual int64_t GetElapsedSessionTime() override;
107 |
108 | virtual int64_t GetElapsedTimeForPreviousSession() override;
109 |
110 | virtual int64_t GetElapsedTimeFromAllSessions() override;
111 |
112 | ////////////////////////////////////////////////////////
113 |
114 | virtual void EnableAdvertisingId(bool value) override;
115 |
116 | virtual void OnQuit() override;
117 |
118 | virtual void SetWritablePath(std::string const& path) override;
119 | };
120 | }
121 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/GameAnalyticsModule.cpp:
--------------------------------------------------------------------------------
1 | #include "GameAnalyticsModule.h"
2 | #include "GameAnalytics.h"
3 | #include "GameAnalyticsProvider.h"
4 | #include "Misc/ConfigCacheIni.h"
5 |
6 | #define GA_PROJECT_SETTINGS TEXT("/Script/GameAnalyticsEditor.GameAnalyticsProjectSettings")
7 |
8 | IMPLEMENT_MODULE( FGameAnalyticsModule, GameAnalytics )
9 |
10 | FGameAnalyticsModule::FGameAnalyticsProjectSettings::PlatformInfo FGameAnalyticsModule::FGameAnalyticsProjectSettings::GetActivePlatform() const
11 | {
12 | #if PLATFORM_IOS
13 | return iOS;
14 | #elif PLATFORM_ANDROID
15 | return Android;
16 | #elif PLATFORM_MAC
17 | return Mac;
18 | #elif PLATFORM_WINDOWS
19 | return Windows;
20 | #elif PLATFORM_LINUX
21 | return Linux;
22 | #else
23 | return {};
24 | #endif
25 | }
26 |
27 | void FGameAnalyticsModule::StartupModule()
28 | {
29 | UE_LOG(LogGameAnalytics, Display, TEXT("FGameAnalyticsModule Constructor"));
30 |
31 | GameAnalytics = NewObject(GetTransientPackage(), UGameAnalytics::StaticClass(), "GameAnalytics", EObjectFlags::RF_Standalone);
32 | GameAnalytics->AddToRoot();
33 |
34 | GameAnalyticsProvider = MakeShareable(new FGameAnalyticsProvider(GameAnalytics));
35 | }
36 |
37 | void FGameAnalyticsModule::ShutdownModule()
38 | {
39 | if (!GExitPurge && IsValid(GameAnalytics))
40 | {
41 | GameAnalytics->RemoveFromRoot();
42 | }
43 |
44 | GameAnalytics = nullptr;
45 | }
46 |
47 | #if (ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 13) || (ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 0)
48 | TSharedPtr FGameAnalyticsModule::CreateAnalyticsProvider(const FAnalyticsProviderConfigurationDelegate& GetConfigValue) const
49 | {
50 | return GameAnalyticsProvider;
51 | }
52 | #else
53 | TSharedPtr FGameAnalyticsModule::CreateAnalyticsProvider(const FAnalytics::FProviderConfigurationDelegate& GetConfigValue) const
54 | {
55 | return GameAnalyticsProvider;
56 | }
57 | #endif
58 |
59 | FGameAnalyticsModule::FGameAnalyticsProjectSettings FGameAnalyticsModule::LoadProjectSettings()
60 | {
61 | FGameAnalyticsProjectSettings Settings;
62 |
63 | if (!GConfig) return Settings;
64 |
65 | // Android
66 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("AndroidGameKey"), Settings.Android.GameKey, GetIniName()))
67 | {
68 | Settings.Android.GameKey = TEXT("");
69 | }
70 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("AndroidSecretKey"), Settings.Android.SecretKey, GetIniName()))
71 | {
72 | Settings.Android.SecretKey = TEXT("");
73 | }
74 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("AndroidBuild"), Settings.Android.Build, GetIniName()))
75 | {
76 | Settings.Android.Build = TEXT("0.1");
77 | }
78 |
79 | // iOS
80 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("IosGameKey"), Settings.iOS.GameKey, GetIniName()))
81 | {
82 | Settings.iOS.GameKey = TEXT("");
83 | }
84 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("IosSecretKey"), Settings.iOS.SecretKey, GetIniName()))
85 | {
86 | Settings.iOS.SecretKey = TEXT("");
87 | }
88 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("IosBuild"), Settings.iOS.Build, GetIniName()))
89 | {
90 | Settings.iOS.Build = TEXT("0.1");
91 | }
92 |
93 | // MacOS
94 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("MacGameKey"), Settings.Mac.GameKey, GetIniName()))
95 | {
96 | Settings.Mac.GameKey = TEXT("");
97 | }
98 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("MacSecretKey"), Settings.Mac.SecretKey, GetIniName()))
99 | {
100 | Settings.Mac.SecretKey = TEXT("");
101 | }
102 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("MacBuild"), Settings.Mac.Build, GetIniName()))
103 | {
104 | Settings.Mac.Build = TEXT("0.1");
105 | }
106 |
107 | // Windows
108 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("WindowsGameKey"), Settings.Windows.GameKey, GetIniName()))
109 | {
110 | Settings.Windows.GameKey = TEXT("");
111 | }
112 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("WindowsSecretKey"), Settings.Windows.SecretKey, GetIniName()))
113 | {
114 | Settings.Windows.SecretKey = TEXT("");
115 | }
116 | if(!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("WindowsBuild"), Settings.Windows.Build, GetIniName()))
117 | {
118 | Settings.Windows.Build = TEXT("0.1");
119 | }
120 |
121 | // Linux
122 | if (!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("LinuxGameKey"), Settings.Linux.GameKey, GetIniName()))
123 | {
124 | Settings.Linux.GameKey = TEXT("");
125 | }
126 | if (!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("LinuxSecretKey"), Settings.Linux.SecretKey, GetIniName()))
127 | {
128 | Settings.Linux.SecretKey = TEXT("");
129 | }
130 | if (!GConfig->GetString(GA_PROJECT_SETTINGS, TEXT("LinuxBuild"), Settings.Linux.Build, GetIniName()))
131 | {
132 | Settings.Linux.Build = TEXT("0.1");
133 | }
134 |
135 | // Global options
136 | if(!GConfig->GetBool(GA_PROJECT_SETTINGS, TEXT("UseManualSessionHandling"), Settings.UseManualSessionHandling, GetIniName()))
137 | {
138 | Settings.UseManualSessionHandling = false;
139 | }
140 | if(!GConfig->GetBool(GA_PROJECT_SETTINGS, TEXT("AutoDetectAppVersion"), Settings.AutoDetectAppVersion, GetIniName()))
141 | {
142 | Settings.AutoDetectAppVersion = false;
143 | }
144 | if (!GConfig->GetBool(GA_PROJECT_SETTINGS, TEXT("DisableDeviceInfo"), Settings.DisableDeviceInfo, GetIniName()))
145 | {
146 | Settings.DisableDeviceInfo = false;
147 | }
148 | if (!GConfig->GetBool(GA_PROJECT_SETTINGS, TEXT("UseErrorReporting"), Settings.UseErrorReporting, GetIniName()))
149 | {
150 | Settings.UseErrorReporting = true;
151 | }
152 | if(!GConfig->GetBool(GA_PROJECT_SETTINGS, TEXT("InfoLogBuild"), Settings.InfoLogBuild, GetIniName()))
153 | {
154 | Settings.InfoLogBuild = true;
155 | }
156 | if(!GConfig->GetBool(GA_PROJECT_SETTINGS, TEXT("VerboseLogBuild"), Settings.VerboseLogBuild, GetIniName()))
157 | {
158 | Settings.VerboseLogBuild = false;
159 | }
160 |
161 | GConfig->GetArray(GA_PROJECT_SETTINGS, TEXT("+CustomDimensions01"), Settings.CustomDimensions01, GetIniName());
162 | GConfig->GetArray(GA_PROJECT_SETTINGS, TEXT("+CustomDimensions02"), Settings.CustomDimensions02, GetIniName());
163 | GConfig->GetArray(GA_PROJECT_SETTINGS, TEXT("+CustomDimensions03"), Settings.CustomDimensions03, GetIniName());
164 | GConfig->GetArray(GA_PROJECT_SETTINGS, TEXT("+ResourceCurrencies"), Settings.ResourceCurrencies, GetIniName());
165 | GConfig->GetArray(GA_PROJECT_SETTINGS, TEXT("+ResourceItemTypes"), Settings.ResourceItemTypes, GetIniName());
166 |
167 | return Settings;
168 | }
169 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/GA-SDK-CPP/GameAnalytics/GameAnalytics.h:
--------------------------------------------------------------------------------
1 | //
2 | // GA-SDK-CPP
3 | // Copyright 2018 GameAnalytics C++ SDK. All rights reserved.
4 | //
5 |
6 | #pragma once
7 |
8 | #include "GameAnalytics/GATypes.h"
9 |
10 | namespace gameanalytics
11 | {
12 | class GameAnalytics
13 | {
14 | public:
15 |
16 | /**
17 | * @brief: sets the available custom dimensions for index 1, needs to be called before initialization
18 | *
19 | * @param customDimensions: valid values to be used as customDimension0
20 | */
21 | static void configureAvailableCustomDimensions01(const StringVector &customDimensions);
22 |
23 | /**
24 | * @brief: sets the available custom dimensions for index 2, needs to be called before initialization
25 | *
26 | * @param customDimensions: valid values
27 | */
28 | static void configureAvailableCustomDimensions02(const StringVector &customDimensions);
29 |
30 | /**
31 | * @brief: sets the available custom dimensions for index 3, needs to be called before initialization
32 | *
33 | * @param customDimensions: valid values to be used as customDimension3
34 | */
35 | static void configureAvailableCustomDimensions03(const StringVector &customDimensions);
36 |
37 | /**
38 | * @brief
39 | *
40 | * @param resourceCurrencies
41 | */
42 | static void configureAvailableResourceCurrencies(const StringVector &resourceCurrencies);
43 | static void configureAvailableResourceItemTypes(const StringVector &resourceItemTypes);
44 |
45 | static void configureBuild(std::string const& build);
46 | static void configureWritablePath(std::string const& writablePath);
47 | static void configureBuildPlatform(std::string const& platform);
48 | static void configureCustomLogHandler(const LogHandler &logHandler);
49 | static void disableDeviceInfo();
50 | static void configureDeviceModel(std::string const& deviceModel);
51 | static void configureDeviceManufacturer(std::string const& deviceManufacturer);
52 |
53 | // the version of SDK code used in an engine. Used for sdk_version field.
54 | // !! if set then it will override the SdkWrapperVersion.
55 | // example "unity 4.6.9"
56 | static void configureSdkGameEngineVersion(std::string const& sdkGameEngineVersion);
57 | // the version of the game engine (if used and version is available)
58 | static void configureGameEngineVersion(std::string const& engineVersion);
59 |
60 | static void configureUserId(std::string const& uId);
61 |
62 | static void configureExternalUserId(std::string const& extId);
63 |
64 | // initialize - starting SDK (need configuration before starting)
65 | static void initialize(std::string const& gameKey, std::string const& gameSecret);
66 |
67 | // add events
68 | static void addBusinessEvent(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& customFields = "", bool mergeFields = false);
69 |
70 | static void addResourceEvent(EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& customFields = "", bool mergeFields = false);
71 |
72 | static void addProgressionEvent(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02 = "", std::string const& progression03 = "", std::string const& customFields = "", bool mergeFields = false);
73 | static void addProgressionEvent(EGAProgressionStatus progressionStatus, int score, std::string const& progression01, std::string const& progression02 = "", std::string const& progression03 = "", std::string const& customFields = "", bool mergeFields = false);
74 |
75 | static void addDesignEvent(std::string const& eventId, std::string const& customFields = "", bool mergeFields = false);
76 | static void addDesignEvent(std::string const& eventId, double value, std::string const& customFields = "", bool mergeFields = false);
77 |
78 | static void addErrorEvent(EGAErrorSeverity severity, std::string const& message, std::string const& customFields = "", bool mergeFields = false);
79 |
80 | // set calls can be changed at any time (pre- and post-initialize)
81 | // some calls only work after a configure is called (setCustomDimension)
82 | static void setEnabledInfoLog(bool flag);
83 | static void setEnabledVerboseLog(bool flag);
84 | static void setEnabledManualSessionHandling(bool flag);
85 | static void setEnabledErrorReporting(bool flag);
86 | static void setEnabledEventSubmission(bool flag);
87 | static void setCustomDimension01(std::string const& dimension01);
88 | static void setCustomDimension02(std::string const& dimension02);
89 | static void setCustomDimension03(std::string const& dimension03);
90 |
91 | /////////// HEALTH EVENT
92 |
93 | static void enableSDKInitEvent(bool value = true);
94 | static void enableMemoryHistogram(bool value = true);
95 | static void enableFPSHistogram(FPSTracker fpsTracker, bool value = true);
96 | static void enableHardwareTracking(bool value = true);
97 |
98 | ///////////
99 |
100 | static void setGlobalCustomEventFields(std::string const& customFields);
101 |
102 | static void startSession();
103 | static void endSession();
104 |
105 | static std::string getRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue = "");
106 | static std::string getRemoteConfigsValueAsJson(std::string const& key);
107 |
108 |
109 | static bool isRemoteConfigsReady();
110 | static void addRemoteConfigsListener(const std::shared_ptr &listener);
111 | static void removeRemoteConfigsListener(const std::shared_ptr &listener);
112 |
113 | static std::string getRemoteConfigsContentAsString();
114 |
115 | static std::string getUserId();
116 | static std::string getExternalUserId();
117 |
118 | static std::string getABTestingId();
119 | static std::string getABTestingVariantId();
120 |
121 | static int64_t getElapsedSessionTime();
122 | static int64_t getElapsedTimeFromAllSessions();
123 | static int64_t getElapsedTimeForPreviousSession();
124 |
125 | // game state changes
126 | // will affect how session is started / ended
127 | static void onResume();
128 | static void onSuspend();
129 | static void onQuit();
130 |
131 | static bool isThreadEnding();
132 |
133 | private:
134 |
135 | static bool _endThread;
136 | static bool isSdkReady(bool needsInitialized, bool warn = true, std::string const& message = "");
137 | };
138 |
139 | } // namespace gameanalytics
140 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/ThirdParty/lib/html5/GameAnalyticsUnreal.js:
--------------------------------------------------------------------------------
1 | var GameAnalyticsUnreal = {
2 | js_configureAvailableCustomDimensions01: function(list)
3 | {
4 | gameanalytics.GameAnalytics.configureAvailableCustomDimensions01(JSON.parse(Pointer_stringify(list)));
5 | },
6 | js_configureAvailableCustomDimensions02: function(list)
7 | {
8 | gameanalytics.GameAnalytics.configureAvailableCustomDimensions02(JSON.parse(Pointer_stringify(list)));
9 | },
10 | js_configureAvailableCustomDimensions03: function(list)
11 | {
12 | gameanalytics.GameAnalytics.configureAvailableCustomDimensions03(JSON.parse(Pointer_stringify(list)));
13 | },
14 | js_configureAvailableResourceCurrencies: function(list)
15 | {
16 | gameanalytics.GameAnalytics.configureAvailableResourceCurrencies(JSON.parse(Pointer_stringify(list)));
17 | },
18 | js_configureAvailableResourceItemTypes: function(list)
19 | {
20 | gameanalytics.GameAnalytics.configureAvailableResourceItemTypes(JSON.parse(Pointer_stringify(list)));
21 | },
22 | js_configureSdkGameEngineVersion: function(unitySdkVersion)
23 | {
24 | gameanalytics.GameAnalytics.configureSdkGameEngineVersion(Pointer_stringify(unitySdkVersion));
25 | },
26 | js_configureGameEngineVersion: function(unityEngineVersion)
27 | {
28 | gameanalytics.GameAnalytics.configureGameEngineVersion(Pointer_stringify(unityEngineVersion));
29 | },
30 | js_configureBuild: function(build)
31 | {
32 | gameanalytics.GameAnalytics.configureBuild(Pointer_stringify(build));
33 | },
34 | js_configureUserId: function(userId)
35 | {
36 | gameanalytics.GameAnalytics.configureUserId(Pointer_stringify(userId));
37 | },
38 | js_initialize: function(gamekey, gamesecret)
39 | {
40 | gameanalytics.GameAnalytics.initialize(Pointer_stringify(gamekey), Pointer_stringify(gamesecret));
41 | },
42 | js_setCustomDimension01: function(customDimension)
43 | {
44 | gameanalytics.GameAnalytics.setCustomDimension01(Pointer_stringify(customDimension));
45 | },
46 | js_setCustomDimension02: function(customDimension)
47 | {
48 | gameanalytics.GameAnalytics.setCustomDimension02(Pointer_stringify(customDimension));
49 | },
50 | js_setCustomDimension03: function(customDimension)
51 | {
52 | gameanalytics.GameAnalytics.setCustomDimension03(Pointer_stringify(customDimension));
53 | },
54 | js_addBusinessEvent: function(currency, amount, itemType, itemId, cartType, fields)
55 | {
56 | gameanalytics.GameAnalytics.addBusinessEvent(Pointer_stringify(currency), amount, Pointer_stringify(itemType), Pointer_stringify(itemId), Pointer_stringify(cartType)/*, JSON.parse(Pointer_stringify(fields))*/);
57 | },
58 | js_addResourceEvent: function(flowType, currency, amount, itemType, itemId, fields)
59 | {
60 | gameanalytics.GameAnalytics.addResourceEvent(flowType, Pointer_stringify(currency), amount, Pointer_stringify(itemType), Pointer_stringify(itemId)/*, JSON.parse(Pointer_stringify(fields))*/);
61 | },
62 | js_addProgressionEvent: function(progressionStatus, progression01, progression02, progression03, fields)
63 | {
64 | gameanalytics.GameAnalytics.addProgressionEvent(progressionStatus, Pointer_stringify(progression01), Pointer_stringify(progression02), Pointer_stringify(progression03)/*, JSON.parse(Pointer_stringify(fields))*/);
65 | },
66 | js_addProgressionEventWithScore: function(progressionStatus, progression01, progression02, progression03, score, fields)
67 | {
68 | gameanalytics.GameAnalytics.addProgressionEvent(progressionStatus, Pointer_stringify(progression01), Pointer_stringify(progression02), Pointer_stringify(progression03), score/*, JSON.parse(Pointer_stringify(fields))*/);
69 | },
70 | js_addDesignEvent: function(eventId, fields)
71 | {
72 | gameanalytics.GameAnalytics.addDesignEvent(Pointer_stringify(eventId)/*, JSON.parse(Pointer_stringify(fields))*/);
73 | },
74 | js_addDesignEventWithValue: function(eventId, value, fields)
75 | {
76 | gameanalytics.GameAnalytics.addDesignEvent(Pointer_stringify(eventId), value/*, JSON.parse(Pointer_stringify(fields))*/);
77 | },
78 | js_addErrorEvent: function(severity, message, fields)
79 | {
80 | gameanalytics.GameAnalytics.addErrorEvent(severity, Pointer_stringify(message)/*, JSON.parse(Pointer_stringify(fields))*/);
81 | },
82 | js_setEnabledInfoLog: function(enabled)
83 | {
84 | gameanalytics.GameAnalytics.setEnabledInfoLog(enabled);
85 | },
86 | js_setEnabledVerboseLog: function(enabled)
87 | {
88 | gameanalytics.GameAnalytics.setEnabledVerboseLog(enabled);
89 | },
90 | js_setManualSessionHandling: function(enabled)
91 | {
92 | gameanalytics.GameAnalytics.setEnabledManualSessionHandling(enabled);
93 | },
94 | js_startSession: function()
95 | {
96 | gameanalytics.GameAnalytics.startSession();
97 | },
98 | js_endSession: function()
99 | {
100 | gameanalytics.GameAnalytics.endSession();
101 | },
102 | js_onStop: function()
103 | {
104 | gameanalytics.GameAnalytics.onStop();
105 | },
106 | js_getRemoteConfigsValueAsString: function(key)
107 | {
108 | var returnStr = gameanalytics.GameAnalytics.getRemoteConfigsValueAsString(Pointer_stringify(key));
109 | var bufferSize = lengthBytesUTF8(returnStr) + 1;
110 | var buffer = _malloc(bufferSize);
111 | stringToUTF8(returnStr, buffer, bufferSize);
112 | return buffer;
113 | },
114 | js_getRemoteConfigsValueAsStringWithDefaultValue: function(key, defaultValue)
115 | {
116 | var returnStr = gameanalytics.GameAnalytics.getRemoteConfigsValueAsString(Pointer_stringify(key), Pointer_stringify(defaultValue));
117 | var bufferSize = lengthBytesUTF8(returnStr) + 1;
118 | var buffer = _malloc(bufferSize);
119 | stringToUTF8(returnStr, buffer, bufferSize);
120 | return buffer;
121 | },
122 | js_isRemoteConfigsReady: function()
123 | {
124 | return gameanalytics.GameAnalytics.isRemoteConfigsReady();
125 | },
126 | js_getRemoteConfigsContentAsString: function()
127 | {
128 | var returnStr = gameanalytics.GameAnalytics.getRemoteConfigsContentAsString();
129 | var bufferSize = lengthBytesUTF8(returnStr) + 1;
130 | var buffer = _malloc(bufferSize);
131 | stringToUTF8(returnStr, buffer, bufferSize);
132 | return buffer;
133 | },
134 | js_getABTestingId: function()
135 | {
136 | var returnStr = gameanalytics.GameAnalytics.getABTestingId();
137 | var bufferSize = lengthBytesUTF8(returnStr) + 1;
138 | var buffer = _malloc(bufferSize);
139 | stringToUTF8(returnStr, buffer, bufferSize);
140 | return buffer;
141 | },
142 | js_getABTestingVariantId: function()
143 | {
144 | var returnStr = gameanalytics.GameAnalytics.getABTestingVariantId();
145 | var bufferSize = lengthBytesUTF8(returnStr) + 1;
146 | var buffer = _malloc(bufferSize);
147 | stringToUTF8(returnStr, buffer, bufferSize);
148 | return buffer;
149 | }
150 | };
151 |
152 | mergeInto(LibraryManager.library, GameAnalyticsUnreal);
153 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalyticsEditor/Public/GameAnalyticsProjectSettings.h:
--------------------------------------------------------------------------------
1 | // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2 | #pragma once
3 |
4 | #include "GameAnalyticsProjectSettings.generated.h"
5 |
6 | UCLASS(config=Engine, defaultconfig)
7 | class UGameAnalyticsProjectSettings : public UObject
8 | {
9 | GENERATED_UCLASS_BODY()
10 |
11 | public:
12 |
13 | // Game Key
14 | UPROPERTY(Config, EditAnywhere, Category=IosSetup, Meta=(ToolTip="Your GameAnalytics iOS Game Key - copy/paste from the GA website or log in to autofill it."))
15 | FString IosGameKey;
16 |
17 | // Secret Key
18 | UPROPERTY(Config, EditAnywhere, Category=IosSetup, Meta=(ToolTip="Your GameAnalytics iOS Secret Key - copy/paste from the GA website or log in to autofill it."))
19 | FString IosSecretKey;
20 |
21 | // Build
22 | UPROPERTY(Config, EditAnywhere, Category = IosSetup, Meta=(ToolTip="The current version of the iOS game. Updating the build name for each test version of the game will allow you to filter by build when viewing your data on the GA website."))
23 | FString IosBuild = "0.1";
24 |
25 | // Game Key
26 | UPROPERTY(Config, EditAnywhere, Category=AndroidSetup, Meta=(ToolTip="Your GameAnalytics Android Game Key - copy/paste from the GA website or log in to autofill it."))
27 | FString AndroidGameKey;
28 |
29 | // Secret Key
30 | UPROPERTY(Config, EditAnywhere, Category=AndroidSetup, Meta=(ToolTip="Your GameAnalytics Android Secret Key - copy/paste from the GA website or log in to autofill it."))
31 | FString AndroidSecretKey;
32 |
33 | // Build
34 | UPROPERTY(Config, EditAnywhere, Category = AndroidSetup, Meta=(ToolTip="The current version of the game. Updating the build name for each test version of the game will allow you to filter by build when viewing your data on the GA website."))
35 | FString AndroidBuild = "0.1";
36 |
37 | // Game Key
38 | UPROPERTY(Config, EditAnywhere, Category=MacSetup, Meta=(ToolTip="Your GameAnalytics Mac Game Key - copy/paste from the GA website or log in to autofill it."))
39 | FString MacGameKey;
40 |
41 | // Secret Key
42 | UPROPERTY(Config, EditAnywhere, Category=MacSetup, Meta=(ToolTip="Your GameAnalytics Mac Secret Key - copy/paste from the GA website or log in to autofill it."))
43 | FString MacSecretKey;
44 |
45 | // Build
46 | UPROPERTY(Config, EditAnywhere, Category = MacSetup, Meta=(ToolTip="The current version of the Mac game. Updating the build name for each test version of the game will allow you to filter by build when viewing your data on the GA website."))
47 | FString MacBuild = "0.1";
48 |
49 | // Game Key
50 | UPROPERTY(Config, EditAnywhere, Category=WindowsSetup, Meta=(ToolTip="Your GameAnalytics Windows Game Key - copy/paste from the GA website or log in to autofill it."))
51 | FString WindowsGameKey;
52 |
53 | // Secret Key
54 | UPROPERTY(Config, EditAnywhere, Category=WindowsSetup, Meta=(ToolTip="Your GameAnalytics Windows Secret Key - copy/paste from the GA website or log in to autofill it."))
55 | FString WindowsSecretKey;
56 |
57 | // Build
58 | UPROPERTY(Config, EditAnywhere, Category = WindowsSetup, Meta=(ToolTip="The current version of the Windows game. Updating the build name for each test version of the game will allow you to filter by build when viewing your data on the GA website."))
59 | FString WindowsBuild = "0.1";
60 |
61 | // Game Key
62 | UPROPERTY(Config, EditAnywhere, Category = LinuxSetup, Meta = (ToolTip = "Your GameAnalytics Linux Game Key - copy/paste from the GA website or log in to autofill it."))
63 | FString LinuxGameKey;
64 |
65 | // Secret Key
66 | UPROPERTY(Config, EditAnywhere, Category = LinuxSetup, Meta = (ToolTip = "Your GameAnalytics Linux Secret Key - copy/paste from the GA website or log in to autofill it."))
67 | FString LinuxSecretKey;
68 |
69 | // Build
70 | UPROPERTY(Config, EditAnywhere, Category = LinuxSetup, Meta = (ToolTip = "The current version of the Linux game. Updating the build name for each test version of the game will allow you to filter by build when viewing your data on the GA website."))
71 | FString LinuxBuild = "0.1";
72 |
73 | // Game Key
74 | UPROPERTY(Config, EditAnywhere, Category = Html5Setup, Meta = (ToolTip = "Your GameAnalytics HTML5 Game Key - copy/paste from the GA website or log in to autofill it."))
75 | FString Html5GameKey;
76 |
77 | // Secret Key
78 | UPROPERTY(Config, EditAnywhere, Category = Html5Setup, Meta = (ToolTip = "Your GameAnalytics HTML5 Secret Key - copy/paste from the GA website or log in to autofill it."))
79 | FString Html5SecretKey;
80 |
81 | // Build
82 | UPROPERTY(Config, EditAnywhere, Category = Html5Setup, Meta = (ToolTip = "The current version of the HTML5 game. Updating the build name for each test version of the game will allow you to filter by build when viewing your data on the GA website."))
83 | FString Html5Build = "0.1";
84 |
85 | // Custom Dimensions 01
86 | UPROPERTY(Config, EditAnywhere, Category=CustomDimensions, Meta=(ToolTip="List of custom dimensions 01."))
87 | TArray CustomDimensions01;
88 |
89 | // Custom Dimensions 02
90 | UPROPERTY(Config, EditAnywhere, Category=CustomDimensions, Meta=(ToolTip="List of custom dimensions 02."))
91 | TArray CustomDimensions02;
92 |
93 | // Custom Dimensions 03
94 | UPROPERTY(Config, EditAnywhere, Category=CustomDimensions, Meta=(ToolTip="List of custom dimensions 03."))
95 | TArray CustomDimensions03;
96 |
97 | // Resource Currencies
98 | UPROPERTY(Config, EditAnywhere, Category=ResourceTypes, Meta=(ToolTip="List of Resource Currencies."))
99 | TArray ResourceCurrencies;
100 |
101 | // Resource Item Types
102 | UPROPERTY(Config, EditAnywhere, Category=ResourceTypes, Meta=(ToolTip="List of Resource Item Types."))
103 | TArray ResourceItemTypes;
104 |
105 | // Use custom id
106 | UPROPERTY(Config, EditAnywhere, Category=Advanced, Meta=(ToolTip="Use manual session handling. Manually choose when to end and start a new session. Note initializing of the SDK will automatically start the first session."))
107 | bool UseManualSessionHandling = false;
108 |
109 | // Auto detect app version for build field (only Android and iOS)
110 | UPROPERTY(Config, EditAnywhere, Category=Advanced, Meta=(ToolTip="Auto detect app version to use for build field (only for Android and iOS)."))
111 | bool AutoDetectAppVersion = false;
112 |
113 | // Disable device info (only Mac, Windows and Linux)
114 | UPROPERTY(Config, EditAnywhere, Category = Advanced, Meta = (ToolTip = "Disable device info (only Mac, Windows and Linux)."))
115 | bool DisableDeviceInfo = false;
116 |
117 | // Use Error Reports
118 | UPROPERTY(Config, EditAnywhere, Category = Advanced, Meta = (ToolTip = "Use automatic error reporting."))
119 | bool UseErrorReporting = true;
120 |
121 | // Submit Errors
122 | //UPROPERTY(Config, EditAnywhere, Category=Advanced)
123 | //bool SubmitErrors = true;
124 |
125 | // Submit Average Frames Per Second
126 | //UPROPERTY(Config, EditAnywhere, Category=Advanced)
127 | //bool SubmitAverageFPS = true;
128 |
129 | // Submit Critical Frames Per Second
130 | //UPROPERTY(Config, EditAnywhere, Category=Advanced)
131 | //bool SubmitCriticalFPS = true;
132 |
133 | // Info Log Editor
134 | //UPROPERTY(Config, EditAnywhere, Category=Debug)
135 | //bool InfoLogEditor = true;
136 |
137 | // Info Log Build
138 | UPROPERTY(Config, EditAnywhere, Category=Debug, Meta=(ToolTip="Show info messages from GA in builds (f.x. Xcode for iOS)."))
139 | bool InfoLogBuild = true;
140 |
141 | // Verbose Log Build
142 | UPROPERTY(Config, EditAnywhere, Category=Debug, Meta=(ToolTip="Show full info messages from GA in builds (f.x. Xcode for iOS). Noet that this option includes long JSON messages sent to the server."))
143 | bool VerboseLogBuild = false;
144 | };
145 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/Desktop/GAWrapperCpp.cpp:
--------------------------------------------------------------------------------
1 | #include "GAWrapperCpp.h"
2 | #include "GameAnalytics/GameAnalytics.h"
3 |
4 | namespace gameanalytics
5 | {
6 | void GAWrapperCpp::SetAvailableCustomDimensions01(const std::vector& list) {
7 | GameAnalytics::configureAvailableCustomDimensions01(list);
8 | }
9 |
10 | void GAWrapperCpp::SetAvailableCustomDimensions02(const std::vector& list) {
11 | GameAnalytics::configureAvailableCustomDimensions02(list);
12 | }
13 |
14 | void GAWrapperCpp::SetAvailableCustomDimensions03(const std::vector& list) {
15 | GameAnalytics::configureAvailableCustomDimensions03(list);
16 | }
17 |
18 | void GAWrapperCpp::SetAvailableResourceCurrencies(const std::vector& list) {
19 | GameAnalytics::configureAvailableResourceCurrencies(list);
20 | }
21 |
22 | void GAWrapperCpp::SetAvailableResourceItemTypes(const std::vector& list) {
23 | GameAnalytics::configureAvailableResourceItemTypes(list);
24 | }
25 |
26 | void GAWrapperCpp::SetBuild(std::string const& build) {
27 | GameAnalytics::configureBuild(build);
28 | }
29 |
30 | void GAWrapperCpp::SetAutoDetectAppVersion(bool flag) {
31 | (void)flag;
32 | return;
33 | }
34 |
35 | void GAWrapperCpp::SetCustomUserId(std::string const& userId) {
36 | GameAnalytics::configureUserId(userId);
37 | }
38 |
39 | void GAWrapperCpp::SetSDKVersion(std::string const& gameEngineSdkVersion) {
40 | GameAnalytics::configureSdkGameEngineVersion(gameEngineSdkVersion);
41 | }
42 |
43 | void GAWrapperCpp::SetGameEngineVersion(std::string const& gameEngineVersion) {
44 | GameAnalytics::configureGameEngineVersion(gameEngineVersion);
45 | }
46 |
47 | void GAWrapperCpp::Initialize(std::string const& gameKey, std::string const& gameSecret) {
48 | GameAnalytics::initialize(gameKey, gameSecret);
49 | }
50 |
51 | void GAWrapperCpp::AddBusinessEvent(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& receipt, std::string const& fields, bool mergeFields) {
52 | (void)receipt;
53 | GameAnalytics::addBusinessEvent(currency, amount, itemType, itemId, cartType, fields, mergeFields);
54 | }
55 |
56 | void GAWrapperCpp::AddBusinessEventWithReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& receipt, std::string const& store, std::string const& signature, std::string const& fields, bool mergeFields) {
57 | (void)receipt;
58 | (void)store;
59 | (void)signature;
60 | GameAnalytics::addBusinessEvent(currency, amount, itemType, itemId, cartType, fields, mergeFields);
61 | }
62 |
63 | void GAWrapperCpp::AddBusinessEventAndAutoFetchReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& fields, bool mergeFields) {
64 | GameAnalytics::addBusinessEvent(currency, amount, itemType, itemId, cartType, fields, mergeFields);
65 | }
66 |
67 | void GAWrapperCpp::AddResourceEvent(::EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& fields, bool mergeFields) {
68 | GameAnalytics::addResourceEvent((gameanalytics::EGAResourceFlowType)flowType, currency, amount, itemType, itemId, fields, mergeFields);
69 | }
70 |
71 | void GAWrapperCpp::AddProgressionEvent(::EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, std::string const& fields, bool mergeFields) {
72 | GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, progression01, progression02, progression03, fields, mergeFields);
73 | }
74 |
75 | void GAWrapperCpp::AddProgressionEventWithScore(::EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, std::string const& fields, bool mergeFields) {
76 | GameAnalytics::addProgressionEvent((gameanalytics::EGAProgressionStatus)progressionStatus, score, progression01, progression02, progression03, fields, mergeFields);
77 | }
78 |
79 | void GAWrapperCpp::AddDesignEvent(std::string const& eventId, std::string const& fields, bool mergeFields) {
80 | GameAnalytics::addDesignEvent(eventId, fields, mergeFields);
81 | }
82 |
83 | void GAWrapperCpp::AddDesignEventWithValue(std::string const& eventId, float value, std::string const& fields, bool mergeFields) {
84 | GameAnalytics::addDesignEvent(eventId, value, fields, mergeFields);
85 | }
86 |
87 | void GAWrapperCpp::AddErrorEvent(::EGAErrorSeverity severity, std::string const& message, std::string const& fields, bool mergeFields){
88 | GameAnalytics::addErrorEvent(static_cast(severity), message, fields, mergeFields);
89 | }
90 |
91 | void GAWrapperCpp::AddAdEvent(::EGAAdAction action, ::EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, std::string const& fields, bool mergeFields) {
92 | return; // ad events are not supported on desktop
93 | }
94 |
95 | void GAWrapperCpp::AddAdEventWithDuration(::EGAAdAction action, ::EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, int64_t duration, std::string const& fields, bool mergeFields) {
96 | return; // ad events are not supported on desktop
97 | }
98 |
99 | void GAWrapperCpp::AddAdEventWithReason(::EGAAdAction adAction, ::EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, ::EGAAdError noAdReason, std::string const& fields, bool mergeFields) {
100 | return; // ad events are not supported on desktop
101 | }
102 |
103 | void GAWrapperCpp::SetInfoLog(bool flag) {
104 | GameAnalytics::setEnabledInfoLog(flag);
105 | }
106 |
107 | void GAWrapperCpp::SetVerboseLog(bool flag) {
108 | GameAnalytics::setEnabledVerboseLog(flag);
109 | }
110 |
111 | void GAWrapperCpp::SetEnabledManualSessionHandling(bool flag) {
112 | GameAnalytics::setEnabledManualSessionHandling(flag);
113 | }
114 |
115 | void GAWrapperCpp::SetEnabledErrorReporting(bool flag) {
116 | GameAnalytics::setEnabledErrorReporting(flag);
117 | }
118 |
119 | void GAWrapperCpp::SetEnabledEventSubmission(bool flag, bool doCache) {
120 | (void)doCache;
121 | GameAnalytics::setEnabledErrorReporting(flag);
122 | }
123 |
124 | void GAWrapperCpp::SetCustomDimension01(std::string const& customDimension) {
125 | GameAnalytics::setCustomDimension01(customDimension);
126 | }
127 |
128 | void GAWrapperCpp::SetCustomDimension02(std::string const& customDimension) {
129 | GameAnalytics::setCustomDimension02(customDimension);
130 | }
131 |
132 | void GAWrapperCpp::SetCustomDimension03(std::string const& customDimension) {
133 | GameAnalytics::setCustomDimension03(customDimension);
134 | }
135 |
136 | void GAWrapperCpp::StartSession() {
137 | GameAnalytics::startSession();
138 | }
139 |
140 | void GAWrapperCpp::EndSession() {
141 | GameAnalytics::endSession();
142 | }
143 |
144 | std::string GAWrapperCpp::GetRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue) {
145 | return GameAnalytics::getRemoteConfigsValueAsString(key, defaultValue);
146 | }
147 |
148 | double GAWrapperCpp::GetRemoteConfigsValueAsNumber(std::string const& key, double defaultValue) {
149 | return defaultValue; //return GameAnalytics::getRemoteConfigsValueAsNumber(key, defaultValue);
150 | }
151 |
152 | std::string GAWrapperCpp::GetRemoteConfigsValueAsJson(std::string const& key) {
153 | return ""; //return GameAnalytics::getRemoteConfigsValueAsJson(key);
154 | }
155 |
156 | bool GAWrapperCpp::IsRemoteConfigsReady() {
157 | return GameAnalytics::isRemoteConfigsReady();
158 | }
159 |
160 | std::string GAWrapperCpp::GetRemoteConfigsContentAsString() {
161 | return GameAnalytics::getRemoteConfigsContentAsString();
162 | }
163 |
164 | std::string GAWrapperCpp::GetABTestingId() {
165 | return GameAnalytics::getABTestingId();
166 | }
167 |
168 | std::string GAWrapperCpp::GetABTestingVariantId() {
169 | return GameAnalytics::getABTestingVariantId();
170 | }
171 |
172 | void GAWrapperCpp::EnableAdvertisingId(bool value) {
173 | (void)value; // for desktop advertising ids are not collected
174 | }
175 |
176 | void GAWrapperCpp::EnableSDKInitEvent(bool value) {
177 | GameAnalytics::enableSDKInitEvent(value);
178 | }
179 |
180 | void GAWrapperCpp::EnableFpsHistogram(FPSTracker tracker, bool value) {
181 | GameAnalytics::enableFPSHistogram(tracker, value);
182 | }
183 |
184 | void GAWrapperCpp::EnableMemoryHistogram(bool value) {
185 | GameAnalytics::enableMemoryHistogram(value);
186 | }
187 |
188 | void GAWrapperCpp::EnableHealthHardwareInfo(bool value) {
189 | GameAnalytics::enableHardwareTracking(value);
190 | }
191 |
192 | void GAWrapperCpp::OnQuit() {
193 | GameAnalytics::onQuit();
194 | }
195 |
196 | void GAWrapperCpp::SetWritablePath(std::string const& path) {
197 | GameAnalytics::configureWritablePath(path);
198 | }
199 |
200 | std::string GAWrapperCpp::GetExternalUserId() {
201 | return GameAnalytics::getExternalUserId();
202 | }
203 |
204 | void GAWrapperCpp::SetExternalUserId(const std::string &extUserId) {
205 | return GameAnalytics::configureExternalUserId(extUserId);
206 | }
207 |
208 | std::string GAWrapperCpp::GetUserId() {
209 | return GameAnalytics::getUserId();
210 | }
211 |
212 | void GAWrapperCpp::SetGlobalCustomEventFields(const std::string &customFields) {
213 | GameAnalytics::setGlobalCustomEventFields(customFields);
214 | }
215 |
216 | int64_t GAWrapperCpp::GetElapsedSessionTime() {
217 | return GameAnalytics::getElapsedSessionTime();
218 | }
219 |
220 | int64_t GAWrapperCpp::GetElapsedTimeForPreviousSession() {
221 |
222 | // TODO: implement when supported in cpp SDK
223 | return 0;
224 | }
225 |
226 | int64_t GAWrapperCpp::GetElapsedTimeFromAllSessions() {
227 | return GameAnalytics::getElapsedTimeFromAllSessions();
228 | }
229 |
230 | }
231 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Public/GameAnalytics.h:
--------------------------------------------------------------------------------
1 | //
2 | // GameAnalytics.h
3 | // GA-SDK-IOS
4 | //
5 | // Copyright (c) 2015 GameAnalytics. All rights reserved.
6 | //
7 |
8 | #pragma once
9 |
10 | #include "UObject/Object.h"
11 | #include "Dom/JsonObject.h"
12 |
13 | #include "GAEnums.h"
14 | #include "GAWrapper.h"
15 | #include "GameAnalytics.generated.h"
16 |
17 | DEFINE_LOG_CATEGORY_STATIC(LogGameAnalytics, Display, All);
18 |
19 | USTRUCT(BlueprintType)
20 | struct FGACustomValue
21 | {
22 | GENERATED_BODY();
23 |
24 | UPROPERTY(BlueprintReadWrite, Category = "GameAnalytics")
25 | FString Key;
26 |
27 | UPROPERTY(BlueprintReadWrite, Category = "GameAnalytics")
28 | FString ValueString;
29 |
30 | UPROPERTY(BlueprintReadWrite, Category = "GameAnalytics")
31 | double ValueNumber = 0.0;
32 |
33 | UPROPERTY(BlueprintReadWrite, Category = "GameAnalytics")
34 | bool ValueBool = false;
35 |
36 | UPROPERTY(BlueprintReadWrite, Category = "GameAnalytics")
37 | EGAValueType ValueType = EGAValueType::value_number;
38 | };
39 |
40 | USTRUCT(BlueprintType)
41 | struct GAMEANALYTICS_API FGACustomFields
42 | {
43 | GENERATED_BODY();
44 |
45 | UPROPERTY(BlueprintReadWrite, Category = "GameAnalytics")
46 | TArray Values;
47 |
48 | bool IsEmpty() const;
49 |
50 | void Set(FString const& Key, double Value);
51 | void Set(FString const& Key, FString const& Value);
52 | void Set(FString const& Key, bool Value);
53 |
54 | FString ToString() const;
55 |
56 | TSharedRef ToJson() const;
57 | };
58 |
59 | class UGameAnalyticsPerformance;
60 |
61 | UCLASS(BlueprintType)
62 | class GAMEANALYTICS_API UGameAnalytics : public UObject
63 | {
64 | GENERATED_UCLASS_BODY()
65 |
66 | // pointer to implementation
67 | TUniquePtr _impl;
68 |
69 | // optional performance tracker
70 | UGameAnalyticsPerformance* _performanceTracker = nullptr;
71 |
72 | public:
73 |
74 | virtual void BeginDestroy() override;
75 |
76 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
77 | static UGameAnalytics* GetInstance();
78 |
79 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
80 | void ConfigureAvailableCustomDimensions01(const TArray& List);
81 |
82 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
83 | void ConfigureAvailableCustomDimensions02(const TArray& List);
84 |
85 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
86 | void ConfigureAvailableCustomDimensions03(const TArray& List);
87 |
88 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
89 | void ConfigureAvailableResourceCurrencies(const TArray& List);
90 |
91 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
92 | void ConfigureAvailableResourceItemTypes(const TArray& List);
93 |
94 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
95 | void ConfigureBuild(FString const& Build);
96 |
97 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
98 | void ConfigureAutoDetectAppVersion(bool Flag);
99 |
100 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
101 | void DisableDeviceInfo();
102 |
103 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
104 | void ConfigureUserId(FString const& UserId);
105 |
106 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
107 | void ConfigureExternalUserId(FString const& UserId);
108 |
109 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
110 | void ConfigureSdkGameEngineVersion(const FString& GameEngineSdkVersion);
111 |
112 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
113 | void ConfigureGameEngineVersion(const FString& GameEngineVersion);
114 |
115 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
116 | void Initialize(FString const& GameKey, FString const& GameSecret);
117 |
118 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
119 | void SetEnabledInfoLog(bool Flag);
120 |
121 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
122 | void SetEnabledVerboseLog(bool Flag);
123 |
124 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
125 | void SetEnabledManualSessionHandling(bool Flag);
126 |
127 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
128 | void SetEnabledErrorReporting(bool Flag);
129 |
130 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
131 | void SetEnabledEventSubmission(bool Flag);
132 |
133 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
134 | void StartSession();
135 |
136 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
137 | void EndSession();
138 |
139 | //////////////////////////////////////////////////////
140 |
141 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
142 | void AddBusinessEvent(FString const& Currency, int Amount, FString const& ItemType, FString const& ItemId, FString const& CartType, FString const& Receipt = "", const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
143 |
144 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
145 | void AddBusinessEventAndAutoFetchReceipt(FString const& Currency, int Amount, FString const& ItemType, FString const& ItemId, FString const& CartType, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
146 |
147 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
148 | void AddBusinessEventWithReceipt(FString const& Currency, int Amount, FString const& ItemType, FString const& ItemId, FString const& CartType, FString const& Receipt, FString const& Store, FString const& Signature, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
149 |
150 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
151 | void AddResourceEvent(EGAResourceFlowType FlowType, const FString &Currency, float Amount, const FString &ItemType, const FString &ItemId, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
152 |
153 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
154 | void AddProgressionEvent(EGAProgressionStatus ProgressionStatus, const FString &Progression01, const FString &Progression02 = "", const FString &Progression03 = "", const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
155 |
156 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
157 | void AddProgressionEventWithScore(EGAProgressionStatus ProgressionStatus, int Score, const FString &Progression01 = "", const FString &Progression02 = "", const FString &Progression03 = "", const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
158 |
159 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
160 | void AddDesignEvent(const FString& EventId, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
161 |
162 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
163 | void AddDesignEventWithValue(const FString& EventId, float Value, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
164 |
165 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
166 | void AddErrorEvent(EGAErrorSeverity Severity, const FString& Message, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
167 |
168 | //////////////////////////////////////////////////////
169 | // AD EVENTS ARE ONLY AVAILABLE FOR IOS AND ANDROID //
170 | //////////////////////////////////////////////////////
171 |
172 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
173 | void AddAdEvent(EGAAdAction Action, EGAAdType AdType, const FString& AdSdkName, const FString& AdPlacement, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
174 |
175 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
176 | void AddAdEventWithDuration(EGAAdAction Action, EGAAdType AdType, const FString& AdSdkName, const FString& AdPlacement, int64 Duration, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
177 |
178 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
179 | void AddAdEventWithReason(EGAAdAction Action, EGAAdType AdType, const FString& AdSdkName, const FString& AdPlacement, EGAAdError Reason, const FGACustomFields CustomFields = FGACustomFields(), bool MergeFields = false);
180 |
181 | ////////////////////////////////////////////////////////////
182 |
183 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
184 | void SetCustomDimension01(const FString& CustomDimension);
185 |
186 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
187 | void SetCustomDimension02(const FString& CustomDimension);
188 |
189 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
190 | void SetCustomDimension03(const FString& CustomDimension);
191 |
192 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
193 | FString GetUserId();
194 |
195 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
196 | FString GetExternalUserId();
197 |
198 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
199 | FString GetRemoteConfigsValueAsString(const FString& Key, const FString& DefaultValue = "");
200 |
201 | // FJsonObject cannot be exposed to blueprints
202 | TSharedPtr GetRemoteConfigsValueAsJSON(const FString& key);
203 |
204 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
205 | bool IsRemoteConfigsReady();
206 |
207 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
208 | FString GetRemoteConfigsContentAsString();
209 |
210 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
211 | FString GetABTestingId();
212 |
213 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
214 | FString GetABTestingVariantId();
215 |
216 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
217 | void OnQuit();
218 |
219 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
220 | void EnableAdvertisingId(bool Value);
221 |
222 | ////////////////////////////////////////////////////////////
223 | // HEALTH EVENT
224 | ////////////////////////////////////////////////////////////
225 |
226 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
227 | void EnableSDKInitEvent(bool Value);
228 |
229 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
230 | void EnableFpsHistogram(bool Value);
231 |
232 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
233 | void EnableMemoryHistogram(bool Value);
234 |
235 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
236 | void EnableHealthHardwareInfo(bool Value);
237 |
238 | ////////////////////////////////////////////////////////////
239 |
240 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
241 | int64 GetElapsedSessionTime();
242 |
243 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
244 | int64 GetElapsedTimeFromAllSessions();
245 |
246 | ////////////////////////////////////////////////////////////
247 |
248 | UFUNCTION(BlueprintCallable, Category = "GameAnalytics")
249 | void SetWritablePath(FString const& Path);
250 | };
251 |
252 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Changelog
2 | ---------
3 |
4 | **6.0.0**
5 | * removed static functions, UGameAnalytics is now an object
6 | * added instance of UGameAnalytics inside UGameAnalyticsModule
7 | * refactored the codebase, added GAWrapper to handle different platforms
8 | * removed all duplicate functions inside UGameAnalytics
9 | * exposed all functions to blueprints
10 | * introduced a new performance tracker, improved FPS reporting
11 | * added FPS reporting for desktop platforms
12 | * updated GameAnalytics dependencies to GA SDK C++ v5.0.0, GA iOS v5.0.0 and GA Android v7.0.0
13 | * added playtime metrics tracking and public functions: GetElapsedSessionTime/GetElapsedTimeFromAllSessions
14 | * added support for Remote Configs v2 with json support: GetRemoteConfigsValueAsJSON
15 | * various improvements and bug-fixes
16 |
17 | **5.6.1**
18 | * fixed iOS compilation issues
19 | * fixed linux broken paths for static cpp ga sdk lib
20 |
21 | **5.6.0**
22 | - fixed UE 5.4 or later compilation issues
23 | - **Boot Time in Milliseconds**: Boot time now reported in milliseconds for precise performance metrics.
24 | - **Design Event Values**: Improved the consistency of design event value handling, ensuring more accurate data delivery.
25 | - **Local Cache Path**: Refined the local cache path configuration to automatically use the default writable path, streamlining setup by making `configureWritablePath` optional.
26 | - **Verbose Logging**: more logs are not visible when verbose logging is enabled.
27 |
28 | **5.5.0**
29 | * updated the C++ SDK dependency
30 | * updated user api routes for login
31 | * added partial health feature support for windows/macos/linux
32 |
33 | **5.4.5**
34 | * fixed documentation links
35 | * added experimental health feature
36 |
37 | **5.4.5**
38 | * fixed documentation links
39 | * added experimental health feature
40 |
41 | **5.4.4**
42 | * support for Unreal 5.4
43 | * added iOS privacy manifest
44 |
45 | **5.4.3**
46 | * updated plugin for UE 5.3
47 |
48 | **5.4.2**
49 | * fixed compilation warnings for android (fix for builds using -werror flag)
50 |
51 | **5.4.1**
52 | * fixed a bug where the android library would fail to load in some cases
53 | * implemented new method to retrieve the device name for win64
54 |
55 | **5.4.0**
56 | * support for UE 5.2.0 preview
57 |
58 | **5.3.1**
59 | * fixed a compilation issue on android for ndk25
60 |
61 | **5.3.0**
62 | * updated plugin for unreal 5.1
63 |
64 | **5.2.0**
65 | * added support for unreal 5
66 |
67 | **5.1.14**
68 | * fixed crash on android
69 |
70 | **5.1.13**
71 | * fixed bug in internal error reporting
72 |
73 | **5.1.12**
74 | * small corrections
75 |
76 | **5.1.11**
77 | * restructured location of files
78 |
79 | **5.1.10**
80 | * added event uuid for events sent
81 |
82 | **5.1.9**
83 | * fixed progression tries bug for desktop platforms
84 |
85 | **5.1.8**
86 | * removed imei identifiers and other alternative identifiers from user identifier logic (android)
87 |
88 | **5.1.7**
89 | * added error events to be sent for invalid custom event fields used
90 | * added optional mergeFields argument to event methods to merge with global custom fields instead of overwrite them
91 |
92 | **5.1.6**
93 | * more build error fixes
94 |
95 | **5.1.5**
96 | * fix build errors
97 |
98 | **5.1.4**
99 | * fixed missing custom event fields for when trying to fix missing session end events
100 |
101 | **5.1.3**
102 | * added error reporting option to settings
103 |
104 | **5.1.2**
105 | * added functionality to force a new user in a/b testing without having to uninstall app first, simply use custom user id function to set a new user id which hasn't been used yet
106 |
107 | **5.1.1**
108 | * small compile fix
109 |
110 | **5.1.0**
111 | * added custom event fields feature
112 |
113 | **5.0.1**
114 | * small correct to support unreal engine 4.27
115 |
116 | **5.0.0**
117 | * Changed user identifier logic in preparation for Google changes to GAID. User id for a new install is now a randomised GUID. Existing installs that update SDK will continue using previous identifier logic. It is recommended to update as soon as possible to reduce impact on calculated metrics.
118 | * added support for unreal engine 4.27
119 |
120 | **4.3.15**
121 | * it should now be possible to not show idfa consent dialog if you don't have any third party code that needs to use idfa (ios)
122 | * prepared for google advertising identifier changes (will not use google advertising identifier when user has opted out) (android)
123 |
124 | **4.3.14**
125 | * added idfa consent status field to events (ios)
126 |
127 | **4.3.13**
128 | * added disable device info to settings
129 |
130 | **4.3.12**
131 | * updated client ts validator
132 |
133 | **4.3.11**
134 | * fixed dependencies for iOS (min. XCode 12 required)
135 |
136 | **4.3.10**
137 | * fixed return values for remote configs and ab testing functions
138 |
139 | **4.3.9**
140 | * added support for unreal engine 4.26
141 |
142 | **4.3.8**
143 | * corrected ad event annotation
144 |
145 | **4.3.7**
146 | * added ARM64 architecture to mac libs
147 |
148 | **4.3.6**
149 | * fixed build errors for linux
150 |
151 | **4.3.5**
152 | * fixed log messages output to console in editor
153 |
154 | **4.3.4**
155 | * added editor logs when calling functions in editor play mode
156 |
157 | **4.3.3**
158 | * improved user identifer flow for ios (ios)
159 |
160 | **4.3.2**
161 | * fix to the seperation of sqlite code for some platforms
162 |
163 | **4.3.1**
164 | * seperated sqlite code into its own library (osx, windows, linux)
165 |
166 | **4.3.0**
167 | * updated user identifier flow to prepare for iOS 14 IDFA changes (ios)
168 |
169 | **4.2.1**
170 | * fixed progression event with scores (android)
171 |
172 | **4.2.0**
173 | * exposed functions to get AB testing id and variant id
174 |
175 | **4.1.5**
176 | * fixed link errors for ios
177 |
178 | **4.1.4**
179 | * added support for unreal engine 4.25
180 |
181 | **4.1.3**
182 | * fixed compile errors
183 |
184 | **4.1.2**
185 | * compile error fix for int64
186 |
187 | **4.1.1**
188 | * compile error fixes
189 |
190 | **4.1.0**
191 | * added ad event (ios, android)
192 | * organizations added to games key list
193 |
194 | **4.0.13**
195 | * logo updated
196 |
197 | **4.0.12**
198 | * uplugin fix
199 |
200 | **4.0.11**
201 | * compile fixes
202 |
203 | **4.0.10**
204 | * removed facebook, gender and birthyear methods
205 | * added auto detect app version for build field option (only android, ios)
206 |
207 | **4.0.9**
208 | * changed editor module type from 'Developer' to 'DeveloperTool'
209 |
210 | **4.0.8**
211 | * removed html5 related code
212 |
213 | **4.0.7**
214 | * A/B testing fixes
215 |
216 | **4.0.6**
217 | * removed compile warnings
218 |
219 | **4.0.5**
220 | * added support for Unreal Engine 4.24
221 |
222 | **4.0.4**
223 | * fixed getRemoteConfigsValueAsString (ios)
224 |
225 | **4.0.3**
226 | * remote configs fixes
227 |
228 | **4.0.2**
229 | * corrected naming of function
230 |
231 | **4.0.1**
232 | * small fixes
233 |
234 | **4.0.0**
235 | * Remote Config calls have been updated and the old calls have deprecated. Please see GA documentation for the new SDK calls and migration guide
236 | * A/B testing support added
237 |
238 | **3.1.13**
239 | * compile error fixes for html5
240 |
241 | **3.1.12**
242 | * compile error fixes for html5
243 |
244 | **3.1.11**
245 | * fixes android builds
246 |
247 | **3.1.10**
248 | * fixed build errors
249 |
250 | **3.1.9**
251 | * fixed command center bugs
252 |
253 | **3.1.8**
254 | * added support for unreal engine 4.23
255 |
256 | **3.1.7**
257 | * added check if log files and database can't be created (desktop platforms)
258 |
259 | **3.1.6**
260 | * fixed progression event for desktop platforms
261 | * fixed hanging background thread when closing application down for desktop platforms
262 |
263 | **3.1.5**
264 | * fixes to warnings and errors
265 |
266 | **3.1.4**
267 | * fixed build errors for html5
268 |
269 | **3.1.3**
270 | * fixed initialize method to be able to be called from code
271 |
272 | **3.1.2**
273 | * added support for unreal engine v4.22
274 |
275 | **3.1.1**
276 | * html5 build fix
277 | * various other bug fixes
278 |
279 | **3.1.0**
280 | * added enable/disable event submission function
281 |
282 | **3.0.6**
283 | * fixed business event validation
284 |
285 | **3.0.5**
286 | * updated to support unreal engine 4.21
287 |
288 | **3.0.4**
289 | * android bug fixes
290 |
291 | **3.0.3**
292 | * fixed shutdown bugs for desktop platforms
293 |
294 | **3.0.2**
295 | * fixed thread hanging on shutdown for desktop platforms
296 |
297 | **3.0.1**
298 | * fixed compile errors
299 |
300 | **3.0.0**
301 | * added command center functionality
302 | * added gameanalytics blueprint functions
303 |
304 | **2.6.28**
305 | * fixed more compile errors for mac
306 |
307 | **2.6.27**
308 | * fixed android crash
309 |
310 | **2.6.26**
311 | * fixed compile errors
312 |
313 | **2.6.19**
314 | * compile fixes for android (android)
315 | * updated to be compatible with unreal engine v4.20
316 |
317 | **2.6.18**
318 | * various bug fixes
319 |
320 | **2.6.17**
321 | * fixes building for linux (linux)
322 |
323 | **2.6.16**
324 | * added custom dimensions to design error events
325 | * added option to startsession with gamekey and secretkey instead of getting keys from settings object
326 |
327 | **2.6.15**
328 | * fixed session length bug
329 | * fixed not allowing to add events when session is not started
330 |
331 | **2.6.14**
332 | * fixed crash bug for closing down sdk for desktop platforms (windows, mac, linux)
333 |
334 | **2.6.13**
335 | * iOS support temporarily removed until Epic fixes some issues the iOS toolchain causes in Unreal Engine 4.19
336 |
337 | **2.6.12**
338 | * added compatability for Unreal Engine v4.19
339 |
340 | **2.6.11**
341 | * log library has been replaced which caused some problems on machine with certain locales set (mac, windows, linux)
342 |
343 | **2.6.10**
344 | * bug fix to progression event crashes
345 |
346 | **2.6.9**
347 | * additional fixes to Unreal Engine 4.18 compatability
348 |
349 | **2.6.8**
350 | * fixes to Unreal Engine 4.18 compatability
351 |
352 | **2.6.7**
353 | * fixed javascript library (html5)
354 |
355 | **2.6.6**
356 | * updated to be compatible with Unreal Engine 4.18
357 |
358 | **2.6.5**
359 | * bug fix to android JNI memory leak (android)
360 |
361 | **2.6.4**
362 | * made compatible with Unreal Engine 4.17
363 |
364 | **2.6.3**
365 | * jni bug fix for progression events with scores (android)
366 |
367 | **2.6.2**
368 | * switched to use third party OpenSSL and libCurl libraries bundled with Unreal Engine
369 |
370 | **2.6.1**
371 | * editor UI bug fix when running game in editor viewport with GameAnalytics plugin enabled
372 |
373 | **2.6.0**
374 | * changed the behaviour of using IMEI with the 'READ_PHONE_STATE' permission to guarantee precise analytics for certain regions (android)
375 |
376 | **2.5.5**
377 | * fixed compile warnings
378 |
379 | **2.5.4**
380 | * fixed html5 wrapper to use correct namespace (html5)
381 |
382 | **2.5.3**
383 | * bug fix for end session when using manual session handling
384 |
385 | **2.5.2**
386 | * session length precision improvement
387 |
388 | **2.5.1**
389 | * custom user id bug fix
390 |
391 | **2.5.0**
392 | * added support for linux
393 |
394 | **2.4.0**
395 | * added support for html5
396 |
397 | **2.2.13**
398 | * corrected win32 library (win32)
399 |
400 | **2.2.12**
401 | * bug fix for progression event with score in Android builds (android)
402 |
403 | **2.2.11**
404 | * proguard fix when making distribution build (android)
405 |
406 | **2.2.10**
407 | * possible to set custom dimensions and demographics before initialise
408 |
409 | **2.2.9**
410 | * fixed missing namespace for JNI function calls (android)
411 |
412 | **2.2.8**
413 | * fix for using plugin directly from C++ code in your project
414 |
415 | **2.2.7**
416 | * fix for empty user_id bug (windows, mac)
417 |
418 | **2.2.6**
419 | * added support for both Unreal Engine 4.12 and 4.13
420 |
421 | **2.2.5**
422 | * bug fix to error when cooking and packaging build
423 |
424 | **2.2.4**
425 | * fixed user_id tracking for iOS 10 (ios)
426 | * small fix related to manual session handling (android)
427 |
428 | **2.2.3**
429 | * fix for empty user id in events (mac, windows)
430 |
431 | **2.2.2**
432 | * Updated to be compatible with Unreal 4.13
433 | * Updated Google Play Services libraries to use latest version (android)
434 |
435 | **2.2.1**
436 | * wrong platform in events bug fix (windows, mac)
437 | * crash bug fix (windows, mac)
438 |
439 | **2.2.0**
440 | * added manual session handling
441 |
442 | **2.1.2**
443 | * fixed default GameAnalytics settings values
444 |
445 | **2.1.1**
446 | * bug fix for missing configureUsedId in native iOS lib (ios)
447 |
448 | **2.1.0**
449 | * Windows and Mac support added (windows and mac)
450 |
451 | **2.0.0**
452 | * various Blueprint event bug fixes
453 | * Android support added (android)
454 |
455 | **0.1.3**
456 | * fixed third party include path
457 |
458 | **0.1.2**
459 | * fixed compile warnings for Unreal Engine 4.11
460 |
461 | **0.1.1**
462 | * minor fixes
463 |
464 | **0.1.0**
465 | * initial version (iOS)
466 |
--------------------------------------------------------------------------------
/GameAnalytics/README.md:
--------------------------------------------------------------------------------
1 | # GA-SDK-UNREAL
2 | GameAnalytics SDK for the Unreal Engine.
3 |
4 | Documentation can be found [here](https://docs.gameanalytics.com/integrations/sdk/unreal).
5 |
6 | If you have any issues or feedback regarding the SDK, please contact our friendly support team [here](https://gameanalytics.com/contact).
7 |
8 | > :information_source:
9 | >
10 | > The Unreal SDK include support for **iOS**, **Android**, **HTML5**, **Windows**, **Linux** and **Mac** platforms
11 | >
12 | > Requirements:
13 | > * **Unreal Engine:** 5.3+
14 | > * **iOS:** iOS 10+
15 | > * **Android:** Android API Level 21
16 | > * **Windows:** Minimum specs for UE5
17 | > * **Mac:** Minimum specs for UE5
18 | >
19 |
20 | Changelog
21 | ---------
22 |
23 | **6.1.0**
24 | * support for unreal 5.7:updated ga-cpp-sdk to v5.1.0:exposed internal GameAnalytics instance to blueprints via `GameAnalytics
25 | * GetInstance()`:fixed `FGACustomFields` blueprints
26 |
27 | **6.0.0**
28 | * removed static functions, UGameAnalytics is now an object
29 | * added instance of UGameAnalytics inside UGameAnalyticsModule
30 | * refactored the codebase, added GAWrapper to handle different platforms
31 | * removed all duplicate functions inside UGameAnalytics
32 | * exposed all functions to blueprints
33 | * introduced a new performance tracker, improved FPS reporting
34 | * added FPS reporting for desktop platforms
35 | * updated GameAnalytics dependencies to GA SDK C++ v5.0.0, GA iOS v5.0.0 and GA Android v7.0.0
36 | * added playtime metrics tracking and public functions: GetElapsedSessionTime/GetElapsedTimeFromAllSessions
37 | * added support for Remote Configs v2 with json support: GetRemoteConfigsValueAsJSON
38 | * various improvements and bug-fixes
39 |
40 | **5.6.1**
41 | * fixed iOS compilation issues
42 | * fixed linux broken paths for static cpp ga sdk lib
43 |
44 | **5.6.0**
45 | - fixed UE 5.4 or later compilation issues
46 | - **Boot Time in Milliseconds**: Boot time now reported in milliseconds for precise performance metrics.
47 | - **Design Event Values**: Improved the consistency of design event value handling, ensuring more accurate data delivery.
48 | - **Local Cache Path**: Refined the local cache path configuration to automatically use the default writable path, streamlining setup by making `configureWritablePath` optional.
49 | - **Verbose Logging**: more logs are not visible when verbose logging is enabled.
50 |
51 | **5.5.0**
52 | * updated the C++ SDK dependency
53 | * updated user api routes for login
54 | * added partial health feature support for windows/macos/linux
55 |
56 | **5.4.5**
57 | * fixed documentation links
58 | * added experimental health feature
59 |
60 | **5.4.5**
61 | * fixed documentation links
62 | * added experimental health feature
63 |
64 | **5.4.4**
65 | * support for Unreal 5.4
66 | * added iOS privacy manifest
67 |
68 | **5.4.3**
69 | * updated plugin for UE 5.3
70 |
71 | **5.4.2**
72 | * fixed compilation warnings for android (fix for builds using -werror flag)
73 |
74 | **5.4.1**
75 | * fixed a bug where the android library would fail to load in some cases
76 | * implemented new method to retrieve the device name for win64
77 |
78 | **5.4.0**
79 | * support for UE 5.2.0 preview
80 |
81 | **5.3.1**
82 | * fixed a compilation issue on android for ndk25
83 |
84 | **5.3.0**
85 | * updated plugin for unreal 5.1
86 |
87 | **5.2.0**
88 | * added support for unreal 5
89 |
90 | **5.1.14**
91 | * fixed crash on android
92 |
93 | **5.1.13**
94 | * fixed bug in internal error reporting
95 |
96 | **5.1.12**
97 | * small corrections
98 |
99 | **5.1.11**
100 | * restructured location of files
101 |
102 | **5.1.10**
103 | * added event uuid for events sent
104 |
105 | **5.1.9**
106 | * fixed progression tries bug for desktop platforms
107 |
108 | **5.1.8**
109 | * removed imei identifiers and other alternative identifiers from user identifier logic (android)
110 |
111 | **5.1.7**
112 | * added error events to be sent for invalid custom event fields used
113 | * added optional mergeFields argument to event methods to merge with global custom fields instead of overwrite them
114 |
115 | **5.1.6**
116 | * more build error fixes
117 |
118 | **5.1.5**
119 | * fix build errors
120 |
121 | **5.1.4**
122 | * fixed missing custom event fields for when trying to fix missing session end events
123 |
124 | **5.1.3**
125 | * added error reporting option to settings
126 |
127 | **5.1.2**
128 | * added functionality to force a new user in a/b testing without having to uninstall app first, simply use custom user id function to set a new user id which hasn't been used yet
129 |
130 | **5.1.1**
131 | * small compile fix
132 |
133 | **5.1.0**
134 | * added custom event fields feature
135 |
136 | **5.0.1**
137 | * small correct to support unreal engine 4.27
138 |
139 | **5.0.0**
140 | * Changed user identifier logic in preparation for Google changes to GAID. User id for a new install is now a randomised GUID. Existing installs that update SDK will continue using previous identifier logic. It is recommended to update as soon as possible to reduce impact on calculated metrics.
141 | * added support for unreal engine 4.27
142 |
143 | **4.3.15**
144 | * it should now be possible to not show idfa consent dialog if you don't have any third party code that needs to use idfa (ios)
145 | * prepared for google advertising identifier changes (will not use google advertising identifier when user has opted out) (android)
146 |
147 | **4.3.14**
148 | * added idfa consent status field to events (ios)
149 |
150 | **4.3.13**
151 | * added disable device info to settings
152 |
153 | **4.3.12**
154 | * updated client ts validator
155 |
156 | **4.3.11**
157 | * fixed dependencies for iOS (min. XCode 12 required)
158 |
159 | **4.3.10**
160 | * fixed return values for remote configs and ab testing functions
161 |
162 | **4.3.9**
163 | * added support for unreal engine 4.26
164 |
165 | **4.3.8**
166 | * corrected ad event annotation
167 |
168 | **4.3.7**
169 | * added ARM64 architecture to mac libs
170 |
171 | **4.3.6**
172 | * fixed build errors for linux
173 |
174 | **4.3.5**
175 | * fixed log messages output to console in editor
176 |
177 | **4.3.4**
178 | * added editor logs when calling functions in editor play mode
179 |
180 | **4.3.3**
181 | * improved user identifer flow for ios (ios)
182 |
183 | **4.3.2**
184 | * fix to the seperation of sqlite code for some platforms
185 |
186 | **4.3.1**
187 | * seperated sqlite code into its own library (osx, windows, linux)
188 |
189 | **4.3.0**
190 | * updated user identifier flow to prepare for iOS 14 IDFA changes (ios)
191 |
192 | **4.2.1**
193 | * fixed progression event with scores (android)
194 |
195 | **4.2.0**
196 | * exposed functions to get AB testing id and variant id
197 |
198 | **4.1.5**
199 | * fixed link errors for ios
200 |
201 | **4.1.4**
202 | * added support for unreal engine 4.25
203 |
204 | **4.1.3**
205 | * fixed compile errors
206 |
207 | **4.1.2**
208 | * compile error fix for int64
209 |
210 | **4.1.1**
211 | * compile error fixes
212 |
213 | **4.1.0**
214 | * added ad event (ios, android)
215 | * organizations added to games key list
216 |
217 | **4.0.13**
218 | * logo updated
219 |
220 | **4.0.12**
221 | * uplugin fix
222 |
223 | **4.0.11**
224 | * compile fixes
225 |
226 | **4.0.10**
227 | * removed facebook, gender and birthyear methods
228 | * added auto detect app version for build field option (only android, ios)
229 |
230 | **4.0.9**
231 | * changed editor module type from 'Developer' to 'DeveloperTool'
232 |
233 | **4.0.8**
234 | * removed html5 related code
235 |
236 | **4.0.7**
237 | * A/B testing fixes
238 |
239 | **4.0.6**
240 | * removed compile warnings
241 |
242 | **4.0.5**
243 | * added support for Unreal Engine 4.24
244 |
245 | **4.0.4**
246 | * fixed getRemoteConfigsValueAsString (ios)
247 |
248 | **4.0.3**
249 | * remote configs fixes
250 |
251 | **4.0.2**
252 | * corrected naming of function
253 |
254 | **4.0.1**
255 | * small fixes
256 |
257 | **4.0.0**
258 | * Remote Config calls have been updated and the old calls have deprecated. Please see GA documentation for the new SDK calls and migration guide
259 | * A/B testing support added
260 |
261 | **3.1.13**
262 | * compile error fixes for html5
263 |
264 | **3.1.12**
265 | * compile error fixes for html5
266 |
267 | **3.1.11**
268 | * fixes android builds
269 |
270 | **3.1.10**
271 | * fixed build errors
272 |
273 | **3.1.9**
274 | * fixed command center bugs
275 |
276 | **3.1.8**
277 | * added support for unreal engine 4.23
278 |
279 | **3.1.7**
280 | * added check if log files and database can't be created (desktop platforms)
281 |
282 | **3.1.6**
283 | * fixed progression event for desktop platforms
284 | * fixed hanging background thread when closing application down for desktop platforms
285 |
286 | **3.1.5**
287 | * fixes to warnings and errors
288 |
289 | **3.1.4**
290 | * fixed build errors for html5
291 |
292 | **3.1.3**
293 | * fixed initialize method to be able to be called from code
294 |
295 | **3.1.2**
296 | * added support for unreal engine v4.22
297 |
298 | **3.1.1**
299 | * html5 build fix
300 | * various other bug fixes
301 |
302 | **3.1.0**
303 | * added enable/disable event submission function
304 |
305 | **3.0.6**
306 | * fixed business event validation
307 |
308 | **3.0.5**
309 | * updated to support unreal engine 4.21
310 |
311 | **3.0.4**
312 | * android bug fixes
313 |
314 | **3.0.3**
315 | * fixed shutdown bugs for desktop platforms
316 |
317 | **3.0.2**
318 | * fixed thread hanging on shutdown for desktop platforms
319 |
320 | **3.0.1**
321 | * fixed compile errors
322 |
323 | **3.0.0**
324 | * added command center functionality
325 | * added gameanalytics blueprint functions
326 |
327 | **2.6.28**
328 | * fixed more compile errors for mac
329 |
330 | **2.6.27**
331 | * fixed android crash
332 |
333 | **2.6.26**
334 | * fixed compile errors
335 |
336 | **2.6.19**
337 | * compile fixes for android (android)
338 | * updated to be compatible with unreal engine v4.20
339 |
340 | **2.6.18**
341 | * various bug fixes
342 |
343 | **2.6.17**
344 | * fixes building for linux (linux)
345 |
346 | **2.6.16**
347 | * added custom dimensions to design error events
348 | * added option to startsession with gamekey and secretkey instead of getting keys from settings object
349 |
350 | **2.6.15**
351 | * fixed session length bug
352 | * fixed not allowing to add events when session is not started
353 |
354 | **2.6.14**
355 | * fixed crash bug for closing down sdk for desktop platforms (windows, mac, linux)
356 |
357 | **2.6.13**
358 | * iOS support temporarily removed until Epic fixes some issues the iOS toolchain causes in Unreal Engine 4.19
359 |
360 | **2.6.12**
361 | * added compatability for Unreal Engine v4.19
362 |
363 | **2.6.11**
364 | * log library has been replaced which caused some problems on machine with certain locales set (mac, windows, linux)
365 |
366 | **2.6.10**
367 | * bug fix to progression event crashes
368 |
369 | **2.6.9**
370 | * additional fixes to Unreal Engine 4.18 compatability
371 |
372 | **2.6.8**
373 | * fixes to Unreal Engine 4.18 compatability
374 |
375 | **2.6.7**
376 | * fixed javascript library (html5)
377 |
378 | **2.6.6**
379 | * updated to be compatible with Unreal Engine 4.18
380 |
381 | **2.6.5**
382 | * bug fix to android JNI memory leak (android)
383 |
384 | **2.6.4**
385 | * made compatible with Unreal Engine 4.17
386 |
387 | **2.6.3**
388 | * jni bug fix for progression events with scores (android)
389 |
390 | **2.6.2**
391 | * switched to use third party OpenSSL and libCurl libraries bundled with Unreal Engine
392 |
393 | **2.6.1**
394 | * editor UI bug fix when running game in editor viewport with GameAnalytics plugin enabled
395 |
396 | **2.6.0**
397 | * changed the behaviour of using IMEI with the 'READ_PHONE_STATE' permission to guarantee precise analytics for certain regions (android)
398 |
399 | **2.5.5**
400 | * fixed compile warnings
401 |
402 | **2.5.4**
403 | * fixed html5 wrapper to use correct namespace (html5)
404 |
405 | **2.5.3**
406 | * bug fix for end session when using manual session handling
407 |
408 | **2.5.2**
409 | * session length precision improvement
410 |
411 | **2.5.1**
412 | * custom user id bug fix
413 |
414 | **2.5.0**
415 | * added support for linux
416 |
417 | **2.4.0**
418 | * added support for html5
419 |
420 | **2.2.13**
421 | * corrected win32 library (win32)
422 |
423 | **2.2.12**
424 | * bug fix for progression event with score in Android builds (android)
425 |
426 | **2.2.11**
427 | * proguard fix when making distribution build (android)
428 |
429 | **2.2.10**
430 | * possible to set custom dimensions and demographics before initialise
431 |
432 | **2.2.9**
433 | * fixed missing namespace for JNI function calls (android)
434 |
435 | **2.2.8**
436 | * fix for using plugin directly from C++ code in your project
437 |
438 | **2.2.7**
439 | * fix for empty user_id bug (windows, mac)
440 |
441 | **2.2.6**
442 | * added support for both Unreal Engine 4.12 and 4.13
443 |
444 | **2.2.5**
445 | * bug fix to error when cooking and packaging build
446 |
447 | **2.2.4**
448 | * fixed user_id tracking for iOS 10 (ios)
449 | * small fix related to manual session handling (android)
450 |
451 | **2.2.3**
452 | * fix for empty user id in events (mac, windows)
453 |
454 | **2.2.2**
455 | * Updated to be compatible with Unreal 4.13
456 | * Updated Google Play Services libraries to use latest version (android)
457 |
458 | **2.2.1**
459 | * wrong platform in events bug fix (windows, mac)
460 | * crash bug fix (windows, mac)
461 |
462 | **2.2.0**
463 | * added manual session handling
464 |
465 | **2.1.2**
466 | * fixed default GameAnalytics settings values
467 |
468 | **2.1.1**
469 | * bug fix for missing configureUsedId in native iOS lib (ios)
470 |
471 | **2.1.0**
472 | * Windows and Mac support added (windows and mac)
473 |
474 | **2.0.0**
475 | * various Blueprint event bug fixes
476 | * Android support added (android)
477 |
478 | **0.1.3**
479 | * fixed third party include path
480 |
481 | **0.1.2**
482 | * fixed compile warnings for Unreal Engine 4.11
483 |
484 | **0.1.1**
485 | * minor fixes
486 |
487 | **0.1.0**
488 | * initial version (iOS)
489 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/GameAnalyticsProvider.cpp:
--------------------------------------------------------------------------------
1 | #include "GameAnalyticsProvider.h"
2 | #include "GameAnalyticsModule.h"
3 | #include "Misc/ConfigCacheIni.h"
4 | #include "Interfaces/IAnalyticsProvider.h"
5 | #include "GameAnalytics.h"
6 |
7 | #if PLATFORM_WINDOWS
8 | #include "Windows/AllowWindowsPlatformTypes.h"
9 | #endif
10 |
11 | static const TMap kProgressionStrings =
12 | {
13 | {TEXT("start"), EGAProgressionStatus::start},
14 | {TEXT("complete"), EGAProgressionStatus::complete},
15 | {TEXT("fail"), EGAProgressionStatus::fail}
16 | };
17 |
18 | static const TMap kSeverityStrings =
19 | {
20 | {TEXT("debug"), EGAErrorSeverity::debug},
21 | {TEXT("info"), EGAErrorSeverity::info},
22 | {TEXT("warning"), EGAErrorSeverity::warning},
23 | {TEXT("error"), EGAErrorSeverity::error},
24 | {TEXT("critical"), EGAErrorSeverity::critical}
25 | };
26 |
27 | static const TMap kFlowTypes =
28 | {
29 | {TEXT("sink"), EGAResourceFlowType::sink},
30 | {TEXT("source"), EGAResourceFlowType::source},
31 | };
32 |
33 | void GAPrintUsageWarning(const char* func)
34 | {
35 | auto constexpr DOCS_LINK = TEXT("https://docs.gameanalytics.com/integrations/sdk/unreal");
36 | UE_LOG(LogGameAnalytics, Warning, TEXT("%hs(): wrong usage, for correct usage see: %s/event-tracking"), func, DOCS_LINK);
37 | }
38 |
39 | #define GA_USAGE_WARNING() GAPrintUsageWarning(__FUNCTION__)
40 |
41 | #if PLATFORM_IOS
42 | #define GA_GAME_KEY_NAME TEXT("ios_gameKey")
43 | #define GA_SECRET_KEY_NAME TEXT("ios_secretKey")
44 | #elif PLATFORM_ANDROID
45 | #define GA_GAME_KEY_NAME TEXT("android_gameKey")
46 | #define GA_SECRET_KEY_NAME TEXT("android_secretKey")
47 | #elif PLATFORM_MAC
48 | #define GA_GAME_KEY_NAME TEXT("mac_gameKey")
49 | #define GA_SECRET_KEY_NAME TEXT("mac_secretKey")
50 | #elif PLATFORM_WINDOWS
51 | #define GA_GAME_KEY_NAME TEXT("windows_gameKey")
52 | #define GA_SECRET_KEY_NAME TEXT("windows_secretKey")
53 | #elif PLATFORM_LINUX
54 | #define GA_GAME_KEY_NAME TEXT("linux_gameKey")
55 | #define GA_SECRET_KEY_NAME TEXT("linux_secretKey")
56 | #else
57 | #define GA_GAME_KEY_NAME TEXT("")
58 | #define GA_SECRET_KEY_NAME TEXT("")
59 | #endif
60 |
61 | FString FGameAnalyticsProvider::GenerateUserId() const
62 | {
63 | #if (ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 15) || (ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 0)
64 | return FPlatformMisc::GetDeviceId();
65 | #else
66 | return FPlatformMisc::GetUniqueDeviceId();
67 | #endif
68 | }
69 |
70 | FString FGameAnalyticsProvider::GetAnalyticsPath() const
71 | {
72 | #if (ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 18) || (ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 0)
73 | return FPaths::ProjectSavedDir();
74 | #else
75 | return FPaths::GameSavedDir();
76 | #endif
77 | }
78 |
79 | #if !UE_BUILD_SHIPPING
80 | /**
81 | * Verifies that the event name matches GameAnalytics's 32 char limit and warns if it doesn't
82 | */
83 | inline void CheckEventNameLen(const FString& EventName)
84 | {
85 | constexpr int32 kMaxLength = 32;
86 |
87 | const int32 Length = EventName.Len();
88 | if (Length > kMaxLength)
89 | {
90 | UE_LOG(LogGameAnalytics, Warning, TEXT("GameAnalytics event name is too long: %s and will be truncated by GameAnalytics. %i characters max limit."), *EventName, kMaxLength);
91 | }
92 | else if (Length == 0)
93 | {
94 | UE_LOG(LogGameAnalytics, Warning, TEXT("GameAnalytics event name is empty!"));
95 | }
96 | }
97 |
98 | #define WarnIfEventNameIsWrongLength(x) CheckEventNameLen(x)
99 |
100 | #else
101 | // Have these compile out
102 | #define WarnIfEventNameIsWrongLength(x)
103 | #endif
104 |
105 | // Provider
106 | FGameAnalyticsProvider::FGameAnalyticsProvider(UGameAnalytics* GameAnalytics) :
107 | bHasSessionStarted(false),
108 | bHasWrittenFirstEvent(false),
109 | Age(0),
110 | GameAnalytics(GameAnalytics)
111 | {
112 | AnalyticsFilePath = GetAnalyticsPath() + TEXT("Analytics/");
113 | }
114 |
115 | FGameAnalyticsProvider::~FGameAnalyticsProvider()
116 | {
117 | UE_LOG(LogGameAnalytics, Display, TEXT("FGameAnalyticsModule ~FGameAnalyticsProvider"));
118 | }
119 |
120 | void FGameAnalyticsProvider::SetDefaultEventAttributes(TArray&& Attributes)
121 | {
122 | (void)Attributes;
123 | }
124 |
125 | TArray FGameAnalyticsProvider::GetDefaultEventAttributesSafe() const
126 | {
127 | return {};
128 | }
129 |
130 | int32 FGameAnalyticsProvider::GetDefaultEventAttributeCount() const
131 | {
132 | return 0;
133 | }
134 |
135 | FAnalyticsEventAttribute FGameAnalyticsProvider::GetDefaultEventAttribute(int AttributeIndex) const
136 | {
137 | (void)AttributeIndex;
138 | return FAnalyticsEventAttribute();
139 | }
140 |
141 | void FGameAnalyticsProvider::OnQuit()
142 | {
143 | GameAnalytics->OnQuit();
144 | }
145 |
146 | bool FGameAnalyticsProvider::StartSession(const TArray& Attributes)
147 | {
148 | if(!bHasSessionStarted)
149 | {
150 | ProjectSettings = FGameAnalyticsModule::LoadProjectSettings();
151 |
152 | auto PlatformInfo = ProjectSettings.GetActivePlatform();
153 |
154 | GameAnalytics->SetWritablePath(GetAnalyticsPath());
155 |
156 | ////// Enable log
157 | GameAnalytics->SetEnabledInfoLog(ProjectSettings.InfoLogBuild);
158 | GameAnalytics->SetEnabledVerboseLog(ProjectSettings.VerboseLogBuild);
159 |
160 | if(ProjectSettings.AutoDetectAppVersion)
161 | {
162 | GameAnalytics->ConfigureAutoDetectAppVersion(ProjectSettings.AutoDetectAppVersion);
163 | }
164 |
165 | if (ProjectSettings.DisableDeviceInfo)
166 | {
167 | GameAnalytics->DisableDeviceInfo();
168 | }
169 |
170 | //// Configure build version
171 | if(!ProjectSettings.AutoDetectAppVersion)
172 | {
173 | GameAnalytics->ConfigureBuild(PlatformInfo.Build);
174 | }
175 |
176 | ////// Configure available virtual currencies and item types
177 | if (ProjectSettings.ResourceCurrencies.Num() > 0)
178 | {
179 | GameAnalytics->ConfigureAvailableResourceCurrencies(ProjectSettings.ResourceCurrencies);
180 | }
181 |
182 | if (ProjectSettings.ResourceItemTypes.Num() > 0)
183 | {
184 | GameAnalytics->ConfigureAvailableResourceItemTypes(ProjectSettings.ResourceItemTypes);
185 | }
186 |
187 | // Configure available custom dimensions
188 | if (ProjectSettings.CustomDimensions01.Num() > 0)
189 | {
190 | GameAnalytics->ConfigureAvailableCustomDimensions01(ProjectSettings.CustomDimensions01);
191 | }
192 |
193 | if (ProjectSettings.CustomDimensions02.Num() > 0)
194 | {
195 | GameAnalytics->ConfigureAvailableCustomDimensions02(ProjectSettings.CustomDimensions02);
196 | }
197 |
198 | if (ProjectSettings.CustomDimensions03.Num() > 0)
199 | {
200 | GameAnalytics->ConfigureAvailableCustomDimensions03(ProjectSettings.CustomDimensions03);
201 | }
202 |
203 | if(ProjectSettings.UseManualSessionHandling)
204 | {
205 | GameAnalytics->SetEnabledManualSessionHandling(ProjectSettings.UseManualSessionHandling);
206 | }
207 |
208 | GameAnalytics->SetEnabledErrorReporting(ProjectSettings.UseErrorReporting);
209 |
210 | const int32 AttrCount = Attributes.Num();
211 | FString GameKey;
212 | FString SecretKey;
213 | if (AttrCount > 0)
214 | {
215 | for (auto Attr : Attributes)
216 | {
217 | if (Attr.GetName() == GA_GAME_KEY_NAME)
218 | {
219 | GameKey = Attr.GetValue();
220 | }
221 | else if (Attr.GetName() == GA_SECRET_KEY_NAME)
222 | {
223 | SecretKey = Attr.GetValue();
224 | }
225 | }
226 | }
227 | else
228 | {
229 | GameKey = PlatformInfo.GameKey;
230 | SecretKey = PlatformInfo.SecretKey;
231 | }
232 |
233 | GameAnalytics->Initialize(GameKey, SecretKey);
234 | bHasSessionStarted = true;
235 | }
236 | else if(ProjectSettings.UseManualSessionHandling)
237 | {
238 | GameAnalytics->StartSession();
239 | }
240 |
241 | return bHasSessionStarted;
242 | }
243 |
244 | void FGameAnalyticsProvider::EndSession()
245 | {
246 | if (bHasSessionStarted)
247 | {
248 | if(ProjectSettings.UseManualSessionHandling)
249 | {
250 | GameAnalytics->EndSession();
251 | }
252 | else
253 | {
254 | UE_LOG(LogGameAnalytics, Warning, TEXT("FGameAnalyticsProvider::EndSession ignored."));
255 | }
256 | }
257 | }
258 |
259 | void FGameAnalyticsProvider::FlushEvents()
260 | {
261 | UE_LOG(LogGameAnalytics, Warning, TEXT("FGameAnalyticsProvider::FlushEvents ignored."));
262 | }
263 |
264 | void FGameAnalyticsProvider::SetUserID(const FString& InUserID)
265 | {
266 | if(!bHasSessionStarted)
267 | {
268 | UE_LOG(LogGameAnalytics, Display, TEXT("GameAnalytics::SetCustomId('%s')"), *InUserID);
269 | GameAnalytics->ConfigureUserId(InUserID);
270 | UserId = InUserID;
271 | }
272 | else
273 | {
274 | UE_LOG(LogGameAnalytics, Warning, TEXT("FGameAnalyticsProvider::SetCustomId Custom id can only be set when SDK is not initialized."));
275 | }
276 | }
277 |
278 | FString FGameAnalyticsProvider::GetUserID() const
279 | {
280 | return UserId;
281 | }
282 |
283 | FString FGameAnalyticsProvider::GetSessionID() const
284 | {
285 | UE_LOG(LogGameAnalytics, Warning, TEXT("FGameAnalyticsProvider::GetSessionID ignored."));
286 | return SessionId;
287 | }
288 |
289 | bool FGameAnalyticsProvider::SetSessionID(const FString& InSessionID)
290 | {
291 | UE_LOG(LogGameAnalytics, Warning, TEXT("FGameAnalyticsProvider::SetSessionID ignored."));
292 | return !bHasSessionStarted;
293 | }
294 |
295 | void FGameAnalyticsProvider::RecordEvent(const FString& EventName, const TArray& Attributes)
296 | {
297 | const int32 AttrCount = Attributes.Num();
298 | if (AttrCount > 0)
299 | {
300 | // Send an event for each attribute
301 | for (auto& Attr : Attributes)
302 | {
303 | if (Attr.GetName() == TEXT("custom1"))
304 | {
305 | GameAnalytics->SetCustomDimension01(Attr.GetValue());
306 | }
307 | else if (Attr.GetName() == TEXT("custom2"))
308 | {
309 | GameAnalytics->SetCustomDimension02(Attr.GetValue());
310 | }
311 | else if (Attr.GetName() == TEXT("custom3"))
312 | {
313 | GameAnalytics->SetCustomDimension03(Attr.GetValue());
314 | }
315 | else
316 | {
317 | float AttrValue = FCString::Atof(*Attr.GetValue());
318 | GameAnalytics->AddDesignEventWithValue(Attr.GetName(), AttrValue);
319 | }
320 | }
321 | }
322 | else if (EventName.Len() > 0)
323 | {
324 | // Send an event without value
325 | GameAnalytics->AddDesignEvent(EventName);
326 | }
327 | }
328 |
329 | void FGameAnalyticsProvider::SetAge(int InAge)
330 | {
331 | }
332 |
333 | void FGameAnalyticsProvider::SetGender(const FString& InGender)
334 | {
335 | }
336 |
337 | void FGameAnalyticsProvider::RecordError(const FString& Error)
338 | {
339 | GameAnalytics->AddErrorEvent(EGAErrorSeverity::error, Error);
340 | }
341 |
342 | void FGameAnalyticsProvider::RecordError(const FString& Error, const TArray& Attributes)
343 | {
344 | const int32 AttrCount = Attributes.Num();
345 | if (AttrCount > 0)
346 | {
347 | for (auto Attr : Attributes)
348 | {
349 | if (Attr.GetName() == TEXT("severity"))
350 | {
351 | FString const Key = Attr.GetValue().ToLower();
352 | if (!kSeverityStrings.Contains(Key))
353 | {
354 | UE_LOG(LogGameAnalytics, Warning, TEXT("RecordError: Severity value must be either debug, info, warning, error, critical. Error=%s"), *Error);
355 | return;
356 | }
357 |
358 | EGAErrorSeverity ErrorSeverity = kSeverityStrings[Key];
359 | GameAnalytics->AddErrorEvent(ErrorSeverity, Error);
360 | }
361 | }
362 | }
363 | else
364 | {
365 | GA_USAGE_WARNING();
366 | }
367 | }
368 |
369 | void FGameAnalyticsProvider::RecordProgress(const FString& ProgressType, const FString& ProgressHierarchy)
370 | {
371 | FString const Key = ProgressType.ToLower();
372 | if (!kProgressionStrings.Contains(Key))
373 | {
374 | UE_LOG(LogGameAnalytics, Warning, TEXT("RecordProgress: ProgressType value must be either start, complete or fail. ProgressType=%s"), *ProgressType);
375 | return;
376 | }
377 |
378 | EGAProgressionStatus ProgressionStatus = kProgressionStrings[Key];
379 | GameAnalytics->AddProgressionEvent(ProgressionStatus, ProgressHierarchy);
380 | }
381 |
382 | void FGameAnalyticsProvider::RecordProgress(const FString& ProgressType, const FString& ProgressHierarchy, const TArray& Attributes)
383 | {
384 | FString const Key = ProgressType.ToLower();
385 |
386 | if (!kProgressionStrings.Contains(Key))
387 | {
388 | UE_LOG(LogGameAnalytics, Warning, TEXT("RecordProgress: ProgressType value must be either start, complete or fail. ProgressType=%s"), *ProgressType);
389 | return;
390 | }
391 |
392 | EGAProgressionStatus ProgressionStatus = kProgressionStrings[Key];
393 |
394 | for (auto& Attr : Attributes)
395 | {
396 | if (Attr.GetName() == TEXT("value"))
397 | {
398 | FString const& Val = Attr.GetValue();
399 | if(Val.IsNumeric())
400 | {
401 | int32 value = FCString::Atoi(*Val);
402 | GameAnalytics->AddProgressionEventWithScore(ProgressionStatus, value, ProgressHierarchy);
403 | return;
404 | }
405 | }
406 | }
407 |
408 | GameAnalytics->AddProgressionEvent(ProgressionStatus, ProgressHierarchy);
409 | }
410 |
411 | void FGameAnalyticsProvider::RecordProgress(const FString& ProgressType, const TArray& ProgressHierarchy, const TArray& Attributes)
412 | {
413 | FString const Key = ProgressType.ToLower();
414 |
415 | if (!kProgressionStrings.Contains(Key))
416 | {
417 | UE_LOG(LogGameAnalytics, Warning, TEXT("RecordProgress: ProgressType value must be either start, complete or fail. ProgressType=%s"), *ProgressType);
418 | return;
419 | }
420 |
421 | EGAProgressionStatus ProgressionStatus = kProgressionStrings[Key];
422 |
423 | const int32 ProgressHierarchyCount = ProgressHierarchy.Num();
424 | if(ProgressHierarchyCount > 0)
425 | {
426 | bool useValue = false;
427 | int32 value = 0;
428 |
429 | for (auto& Attr : Attributes)
430 | {
431 | UE_LOG(LogGameAnalytics, Warning, TEXT("RecordProgress: Attributes. AttrName=%s"), *Attr.GetName());
432 | if (Attr.GetName() == TEXT("value"))
433 | {
434 | useValue = true;
435 | value = FCString::Atoi(*Attr.GetValue());
436 | break;
437 | }
438 | }
439 |
440 | switch(ProgressHierarchyCount)
441 | {
442 | case 1:
443 | return useValue ?
444 | GameAnalytics->AddProgressionEventWithScore(ProgressionStatus, value, ProgressHierarchy[0]):
445 | GameAnalytics->AddProgressionEvent(ProgressionStatus, ProgressHierarchy[0]);
446 |
447 | case 2:
448 | return useValue ?
449 | GameAnalytics->AddProgressionEventWithScore(ProgressionStatus, value, ProgressHierarchy[0], ProgressHierarchy[1]):
450 | GameAnalytics->AddProgressionEvent(ProgressionStatus, ProgressHierarchy[0], ProgressHierarchy[1]);
451 |
452 | default:
453 | return useValue ?
454 | GameAnalytics->AddProgressionEventWithScore(ProgressionStatus, value, ProgressHierarchy[0], ProgressHierarchy[1], ProgressHierarchy[2]):
455 | GameAnalytics->AddProgressionEvent(ProgressionStatus, ProgressHierarchy[0], ProgressHierarchy[1], ProgressHierarchy[2]);
456 | }
457 | }
458 | else
459 | {
460 | GA_USAGE_WARNING();
461 | }
462 | }
463 |
464 | void FGameAnalyticsProvider::RecordItemPurchase(const FString& ItemId, const FString& Currency, int PerItemCost, int ItemQuantity)
465 | {
466 | UE_LOG(LogGameAnalytics, Warning, TEXT("FGameAnalyticsProvider::RecordItemPurchase(const FString& ItemId, const FString& Currency, int PerItemCost, int ItemQuantity) ignored. Please use instead: FGameAnalyticsProvider::RecordItemPurchase(const FString& ItemId, int ItemQuantity, const TArray& Attributes)"));
467 | }
468 |
469 | void FGameAnalyticsProvider::RecordItemPurchase(const FString& ItemId, int ItemQuantity, const TArray& Attributes)
470 | {
471 | EGAResourceFlowType FlowType = EGAResourceFlowType::source;
472 | FString Currency;
473 | FString ItemType;
474 |
475 | const int32 AttrCount = Attributes.Num();
476 | if (AttrCount > 0)
477 | {
478 | for (auto& Attr : Attributes)
479 | {
480 | if (Attr.GetName() == TEXT("flowType"))
481 | {
482 | FString const Key = Attr.GetValue().ToLower();
483 | if (!kFlowTypes.Contains(Key))
484 | {
485 | UE_LOG(LogGameAnalytics, Warning, TEXT("RecordItemPurchaseError: FlowType value must be either sink or source. flowType=%s"), *Attr.GetValue());
486 | return;
487 | }
488 |
489 | FlowType = kFlowTypes[Key];
490 | }
491 | else if (Attr.GetName() == TEXT("currency"))
492 | {
493 | Currency = Attr.GetValue();
494 | }
495 | else if (Attr.GetName() == TEXT("itemType"))
496 | {
497 | ItemType = Attr.GetValue();
498 | }
499 | }
500 |
501 | if (!Currency.IsEmpty() && !ItemType.IsEmpty())
502 | {
503 | GameAnalytics->AddResourceEvent(FlowType, Currency, ItemQuantity, ItemType, ItemId);
504 | }
505 | else
506 | {
507 | GA_USAGE_WARNING();
508 | }
509 | }
510 | else
511 | {
512 | GA_USAGE_WARNING();
513 | }
514 | }
515 |
516 | void FGameAnalyticsProvider::RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount, const FString& RealCurrencyType, float RealMoneyCost, const FString& PaymentProvider)
517 | {
518 | UE_LOG(LogGameAnalytics, Display, TEXT("FGameAnalyticsProvider::RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount, const FString& RealCurrencyType, float RealMoneyCost, const FString& PaymentProvider) - ignoring call. Instead use: FGameAnalyticsProvider::RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount, const TArray& Attributes)"));
519 | }
520 |
521 | void FGameAnalyticsProvider::RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount)
522 | {
523 | UE_LOG(LogGameAnalytics, Display, TEXT("FGameAnalyticsProvider::RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount) - ignoring call. Instead use: FGameAnalyticsProvider::RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount, const TArray& Attributes)"));
524 | }
525 |
526 | void FGameAnalyticsProvider::RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount, const TArray& Attributes)
527 | {
528 | FString ItemType;
529 | FString ItemId;
530 | FString CartType;
531 | FString Receipt;
532 | FString Signature;
533 | FString Store;
534 | bool AutoFetchReceipt = false;
535 |
536 | const int32 AttrCount = Attributes.Num();
537 | if (AttrCount > 0)
538 | {
539 | for (auto& Attr : Attributes)
540 | {
541 | FString AttrString = Attr.GetName();
542 |
543 | if (Attr.GetName() == TEXT("itemType"))
544 | {
545 | ItemType = Attr.GetValue();
546 | }
547 | else if (Attr.GetName() == TEXT("itemId"))
548 | {
549 | ItemId = Attr.GetValue();
550 | }
551 | else if (Attr.GetName() == TEXT("cartType"))
552 | {
553 | CartType = Attr.GetValue();
554 | }
555 | else if (Attr.GetName() == TEXT("receipt"))
556 | {
557 | Receipt = Attr.GetValue();
558 | }
559 | else if (Attr.GetName() == TEXT("autoFetchReceipt"))
560 | {
561 | if (Attr.GetValue().ToBool())
562 | {
563 | AutoFetchReceipt = true;
564 | }
565 | }
566 | else if (Attr.GetName() == TEXT("signature"))
567 | {
568 | Signature = Attr.GetValue();
569 | }
570 | else if (Attr.GetName() == TEXT("store"))
571 | {
572 | Store = Attr.GetValue();
573 | }
574 | }
575 |
576 | if (!ItemType.IsEmpty() && !ItemId.IsEmpty() && !CartType.IsEmpty())
577 | {
578 | if (!Receipt.IsEmpty())
579 | {
580 | GameAnalytics->AddBusinessEventWithReceipt(GameCurrencyType, GameCurrencyAmount, ItemType, ItemId, CartType, Receipt, Store, Signature);
581 | }
582 | else if(AutoFetchReceipt)
583 | {
584 | GameAnalytics->AddBusinessEventAndAutoFetchReceipt(GameCurrencyType, GameCurrencyAmount, ItemType, ItemId, CartType);
585 | }
586 | else
587 | {
588 | GameAnalytics->AddBusinessEvent(GameCurrencyType, GameCurrencyAmount, ItemType, ItemId, CartType);
589 | }
590 | }
591 | else
592 | {
593 | GA_USAGE_WARNING();
594 | }
595 | }
596 | else
597 | {
598 | GA_USAGE_WARNING();
599 | }
600 | }
601 |
602 | void FGameAnalyticsProvider::RecordCurrencyGiven(const FString& GameCurrencyType, int GameCurrencyAmount)
603 | {
604 | UE_LOG(LogGameAnalytics, Display, TEXT("GameAnalytics::RecordCurrencyGiven - ignoring call"));
605 | }
606 |
607 | void FGameAnalyticsProvider::RecordCurrencyGiven(const FString& GameCurrencyType, int GameCurrencyAmount, const TArray& Attributes)
608 | {
609 | UE_LOG(LogGameAnalytics, Display, TEXT("GameAnalytics::RecordCurrencyGiven - ignoring call"));
610 | }
611 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/GameAnalytics.cpp:
--------------------------------------------------------------------------------
1 | #include "GameAnalytics.h"
2 |
3 | #include "Misc/EngineVersion.h"
4 | #include "AnalyticsEventAttribute.h"
5 | #include "Serialization/JsonWriter.h"
6 | #include "Serialization/JsonSerializer.h"
7 |
8 | #include "GameAnalyticsPerformance.h"
9 | #include "GameAnalyticsModule.h"
10 |
11 | #define GA_VERSION TEXT("6.1.0")
12 |
13 | #if PLATFORM_MAC || PLATFORM_WINDOWS || PLATFORM_LINUX
14 | #define GA_USE_CPP_SDK 1
15 | #include "Desktop/GAWrapperCpp.h"
16 | #else
17 | #define GA_USE_CPP_SDK 0
18 | #if PLATFORM_IOS
19 | #include "IOS/GAWrapperIOS.h"
20 | #elif PLATFORM_ANDROID
21 | #include "Android/GAWrapperAndroid.h"
22 | #endif
23 | #endif
24 |
25 | std::string ToStdString(const FString& str)
26 | {
27 | std::string s = TCHAR_TO_UTF8(*str);
28 | return s;
29 | }
30 |
31 | FString ToFString(std::string const& str)
32 | {
33 | FString s = UTF8_TO_TCHAR(str.c_str());
34 | return s;
35 | }
36 |
37 | std::vector ToStringVector(const TArray& arr)
38 | {
39 | std::vector v;
40 | v.reserve(arr.Num());
41 |
42 | for (const FString& item : arr)
43 | {
44 | v.push_back(ToStdString(item));
45 | }
46 |
47 | return v;
48 | }
49 |
50 | inline constexpr auto BoolToStr(bool flag)
51 | {
52 | return flag ? TEXT("TRUE") : TEXT("FALSE");
53 | }
54 |
55 | void PrintImplWarning(const char* funcName)
56 | {
57 | UE_LOG(LogGameAnalytics, Display, TEXT("UGameAnalytics::%hs(): This platform is not supported (please note GameAnalytics will not work inside the editor!)"), funcName);
58 | }
59 |
60 | #define GA_NOT_SUPPORTED_WARNING() PrintImplWarning(__FUNCTION__)
61 |
62 | void FGACustomFields::Set(FString const& key, double value)
63 | {
64 | FGACustomValue v = {};
65 |
66 | v.Key = key;
67 | v.ValueNumber = value;
68 | v.ValueType = EGAValueType::value_number;
69 |
70 | Values.Push(std::move(v));
71 | }
72 |
73 | void FGACustomFields::Set(FString const& key, FString const& value)
74 | {
75 | FGACustomValue v = {};
76 |
77 | v.Key = key;
78 | v.ValueString = value;
79 | v.ValueType = EGAValueType::value_string;
80 |
81 | Values.Push(std::move(v));
82 | }
83 |
84 | void FGACustomFields::Set(FString const& key, bool value)
85 | {
86 | FGACustomValue v = {};
87 |
88 | v.Key = key;
89 | v.ValueBool = value;
90 | v.ValueType = EGAValueType::value_bool;
91 |
92 | Values.Push(std::move(v));
93 | }
94 |
95 | bool FGACustomFields::IsEmpty() const
96 | {
97 | return Values.Num() == 0;
98 | }
99 |
100 | TSharedRef FGACustomFields::ToJson() const
101 | {
102 | TSharedRef Json = MakeShared();
103 | for(auto& V : Values)
104 | {
105 | if(V.Key.IsEmpty())
106 | {
107 | UE_LOG(LogGameAnalytics, Display, TEXT("Custom field key cannot be empty!"));
108 | continue;
109 | }
110 |
111 | switch(V.ValueType)
112 | {
113 | case EGAValueType::value_string:
114 | {
115 | Json->SetStringField(V.Key, V.ValueString);
116 | break;
117 | }
118 |
119 | case EGAValueType::value_bool:
120 | {
121 | Json->SetBoolField(V.Key, V.ValueBool);
122 | break;
123 | }
124 |
125 | case EGAValueType::value_number:
126 | default:
127 | {
128 | Json->SetNumberField(V.Key, V.ValueNumber);
129 | }
130 | }
131 | }
132 |
133 | return Json;
134 | }
135 |
136 | FString FGACustomFields::ToString() const
137 | {
138 | if(IsEmpty())
139 | {
140 | return TEXT("");
141 | }
142 |
143 | TSharedRef Json = ToJson();
144 |
145 | FString FieldsString;
146 | TSharedRef> Writer = TJsonWriterFactory<>::Create(&FieldsString);
147 | FJsonSerializer::Serialize(Json, Writer);
148 |
149 | return FieldsString;
150 | }
151 |
152 | UGameAnalytics* UGameAnalytics::GetInstance()
153 | {
154 | return FGameAnalyticsModule::Get().GetInstance();
155 | }
156 |
157 | UGameAnalytics::UGameAnalytics(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
158 | {
159 | #if WITH_EDITOR
160 | _impl.Reset(nullptr);
161 | #elif PLATFORM_IOS
162 | _impl.Reset(new gameanalytics::GAWrapperIOS);
163 | #elif PLATFORM_ANDROID
164 | _impl.Reset(new gameanalytics::GAWrapperAndroid);
165 | #elif GA_USE_CPP_SDK
166 | _impl.Reset(new gameanalytics::GAWrapperCpp);
167 | #endif
168 | }
169 |
170 | void UGameAnalytics::BeginDestroy()
171 | {
172 | OnQuit();
173 |
174 | if(IsValid(_performanceTracker))
175 | {
176 | _performanceTracker->RemoveFromRoot();
177 | }
178 |
179 | Super::BeginDestroy();
180 | }
181 |
182 | void UGameAnalytics::ConfigureAvailableCustomDimensions01(const TArray& list)
183 | {
184 | if(_impl)
185 | {
186 | std::vector v = ToStringVector(list);
187 | _impl->SetAvailableCustomDimensions01(v);
188 | }
189 | else
190 | {
191 | GA_NOT_SUPPORTED_WARNING();
192 | }
193 | }
194 |
195 | void UGameAnalytics::ConfigureAvailableCustomDimensions02(const TArray& list)
196 | {
197 | if(_impl)
198 | {
199 | std::vector v = ToStringVector(list);
200 | _impl->SetAvailableCustomDimensions02(v);
201 | }
202 | else
203 | {
204 | GA_NOT_SUPPORTED_WARNING();
205 | }
206 | }
207 |
208 | void UGameAnalytics::ConfigureAvailableCustomDimensions03(const TArray& list)
209 | {
210 | if(_impl)
211 | {
212 | std::vector v = ToStringVector(list);
213 | _impl->SetAvailableCustomDimensions03(v);
214 | }
215 | else
216 | {
217 | GA_NOT_SUPPORTED_WARNING();
218 | }
219 | }
220 |
221 | void UGameAnalytics::ConfigureAvailableResourceCurrencies(const TArray& list)
222 | {
223 | if(_impl)
224 | {
225 | std::vector v = ToStringVector(list);
226 | _impl->SetAvailableResourceCurrencies(v);
227 | }
228 | else
229 | {
230 | GA_NOT_SUPPORTED_WARNING();
231 | }
232 | }
233 |
234 | void UGameAnalytics::ConfigureAvailableResourceItemTypes(const TArray& list)
235 | {
236 | if(_impl)
237 | {
238 | std::vector v = ToStringVector(list);
239 | _impl->SetAvailableResourceItemTypes(v);
240 | }
241 | else
242 | {
243 | GA_NOT_SUPPORTED_WARNING();
244 | }
245 | }
246 |
247 | void UGameAnalytics::ConfigureBuild(FString const& build)
248 | {
249 | if(_impl)
250 | {
251 | _impl->SetBuild(ToStdString(build));
252 | }
253 | else
254 | {
255 | GA_NOT_SUPPORTED_WARNING();
256 | }
257 | }
258 |
259 | void UGameAnalytics::ConfigureAutoDetectAppVersion(bool flag)
260 | {
261 | if(_impl)
262 | {
263 | _impl->SetAutoDetectAppVersion(flag);
264 | }
265 | else
266 | {
267 | GA_NOT_SUPPORTED_WARNING();
268 | }
269 | }
270 |
271 | void UGameAnalytics::DisableDeviceInfo()
272 | {
273 | if(_impl)
274 | {
275 | //_impl->DisableDeviceInfo(flag);
276 | }
277 | else
278 | {
279 | GA_NOT_SUPPORTED_WARNING();
280 | }
281 | }
282 |
283 | void UGameAnalytics::ConfigureUserId(FString const& UserId)
284 | {
285 | if(_impl)
286 | {
287 | _impl->SetCustomUserId(ToStdString(UserId));
288 | }
289 | else
290 | {
291 | GA_NOT_SUPPORTED_WARNING();
292 | }
293 | }
294 |
295 | void UGameAnalytics::ConfigureExternalUserId(FString const& UserId)
296 | {
297 | if (_impl)
298 | {
299 | _impl->SetExternalUserId(ToStdString(UserId));
300 | }
301 | else
302 | {
303 | GA_NOT_SUPPORTED_WARNING();
304 | }
305 | }
306 |
307 | void UGameAnalytics::ConfigureSdkGameEngineVersion(FString const& gameEngineSdkVersion)
308 | {
309 | if(_impl)
310 | {
311 | _impl->SetSDKVersion(ToStdString(gameEngineSdkVersion));
312 | }
313 | else
314 | {
315 | GA_NOT_SUPPORTED_WARNING();
316 | }
317 | }
318 |
319 | void UGameAnalytics::ConfigureGameEngineVersion(FString const& gameEngineVersion)
320 | {
321 | if(_impl)
322 | {
323 | _impl->SetSDKVersion(ToStdString(gameEngineVersion));
324 | }
325 | else
326 | {
327 | GA_NOT_SUPPORTED_WARNING();
328 | }
329 | }
330 |
331 | void UGameAnalytics::Initialize(FString const& gameKey, FString const& gameSecret)
332 | {
333 | if(_impl)
334 | {
335 | // Configure engine version
336 | FString EngineVersionString = FString::Printf(TEXT("unreal %d.%d.%d"), FEngineVersion::Current().GetMajor(), FEngineVersion::Current().GetMinor(), FEngineVersion::Current().GetPatch());
337 | ConfigureGameEngineVersion(EngineVersionString);
338 |
339 | // Configure sdk version
340 | FString SdkVersionString = FString::Printf(TEXT("unreal %s"), GA_VERSION);
341 | ConfigureSdkGameEngineVersion(SdkVersionString);
342 |
343 | _impl->Initialize(ToStdString(gameKey), ToStdString(gameSecret));
344 | }
345 | else
346 | {
347 | GA_NOT_SUPPORTED_WARNING();
348 | }
349 | }
350 |
351 | void UGameAnalytics::AddBusinessEvent(FString const& Currency, int Amount, FString const& ItemType, FString const& ItemId, FString const& CartType, FString const& Receipt, const FGACustomFields CustomFields, bool MergeFields)
352 | {
353 | if(_impl)
354 | {
355 | _impl->AddBusinessEvent(ToStdString(Currency), Amount, ToStdString(ItemType), ToStdString(ItemId), ToStdString(CartType), ToStdString(Receipt), ToStdString(CustomFields.ToString()), MergeFields);
356 | }
357 | else
358 | {
359 | GA_NOT_SUPPORTED_WARNING();
360 | }
361 | }
362 |
363 | void UGameAnalytics::AddBusinessEventAndAutoFetchReceipt(FString const& currency, int amount, FString const& itemType, FString const& itemId, FString const& cartType, const FGACustomFields CustomFields, bool mergeFields)
364 | {
365 | if(_impl)
366 | {
367 | _impl->AddBusinessEventAndAutoFetchReceipt(ToStdString(currency), amount, ToStdString(itemType), ToStdString(itemId), ToStdString(cartType), ToStdString(CustomFields.ToString()), mergeFields);
368 | }
369 | else
370 | {
371 | GA_NOT_SUPPORTED_WARNING();
372 | }
373 | }
374 |
375 | void UGameAnalytics::AddBusinessEventWithReceipt(FString const& Currency, int Amount, FString const& ItemType, FString const& ItemId, FString const& CartType, FString const& Receipt, FString const& Store, FString const& Signature, const FGACustomFields CustomFields, bool MergeFields)
376 | {
377 | if(_impl)
378 | {
379 | _impl->AddBusinessEventWithReceipt(ToStdString(Currency), Amount, ToStdString(ItemType), ToStdString(ItemId), ToStdString(CartType), ToStdString(Receipt), ToStdString(Store), ToStdString(Signature), ToStdString(CustomFields.ToString()), MergeFields);
380 | }
381 | else
382 | {
383 | GA_NOT_SUPPORTED_WARNING();
384 | }
385 | }
386 |
387 | void UGameAnalytics::AddProgressionEvent(EGAProgressionStatus ProgressionStatus, const FString &Progression01, const FString &Progression02, const FString &Progression03, const FGACustomFields CustomFields, bool MergeFields)
388 | {
389 | if(_impl)
390 | {
391 | _impl->AddProgressionEvent(ProgressionStatus, ToStdString(Progression01), ToStdString(Progression02), ToStdString(Progression03), ToStdString(CustomFields.ToString()), MergeFields);
392 | }
393 | else
394 | {
395 | GA_NOT_SUPPORTED_WARNING();
396 | }
397 | }
398 |
399 | void UGameAnalytics::AddProgressionEventWithScore(EGAProgressionStatus ProgressionStatus, int Score, const FString &Progression01, const FString &Progression02, const FString &Progression03, const FGACustomFields CustomFields, bool MergeFields)
400 | {
401 | if(_impl)
402 | {
403 | _impl->AddProgressionEventWithScore(ProgressionStatus, ToStdString(Progression01), ToStdString(Progression02), ToStdString(Progression03), Score, ToStdString(CustomFields.ToString()), MergeFields);
404 | }
405 | else
406 | {
407 | GA_NOT_SUPPORTED_WARNING();
408 | }
409 | }
410 |
411 | void UGameAnalytics::AddDesignEvent(FString const& eventId, const FGACustomFields CustomFields, bool mergeFields)
412 | {
413 | if(_impl)
414 | {
415 | _impl->AddDesignEvent(ToStdString(eventId), ToStdString(CustomFields.ToString()), mergeFields);
416 | }
417 | else
418 | {
419 | GA_NOT_SUPPORTED_WARNING();
420 | }
421 | }
422 |
423 | void UGameAnalytics::AddDesignEventWithValue(FString const& eventId, float value, const FGACustomFields CustomFields, bool mergeFields)
424 | {
425 | if(_impl)
426 | {
427 | _impl->AddDesignEventWithValue(ToStdString(eventId), value, ToStdString(CustomFields.ToString()), mergeFields);
428 | }
429 | else
430 | {
431 | GA_NOT_SUPPORTED_WARNING();
432 | }
433 | }
434 |
435 | void UGameAnalytics::AddErrorEvent(EGAErrorSeverity severity, FString const& message, const FGACustomFields CustomFields, bool mergeFields)
436 | {
437 | if(_impl)
438 | {
439 | _impl->AddErrorEvent(severity, ToStdString(message), ToStdString(CustomFields.ToString()), mergeFields);
440 | }
441 | else
442 | {
443 | GA_NOT_SUPPORTED_WARNING();
444 | }
445 | }
446 |
447 | void UGameAnalytics::AddResourceEvent(EGAResourceFlowType FlowType, const FString& Currency, float Amount, const FString& ItemType, const FString& ItemId, const FGACustomFields CustomFields, bool MergeFields)
448 | {
449 | if(_impl)
450 | {
451 | _impl->AddResourceEvent(FlowType, ToStdString(Currency), Amount, ToStdString(ItemType), ToStdString(ItemId), ToStdString(CustomFields.ToString()), MergeFields);
452 | }
453 | else
454 | {
455 | GA_NOT_SUPPORTED_WARNING();
456 | }
457 | }
458 |
459 | void UGameAnalytics::AddAdEvent(EGAAdAction action, EGAAdType adType, const FString& adSdkName, const FString& adPlacement, const FGACustomFields CustomFields, bool mergeFields)
460 | {
461 | if(_impl)
462 | {
463 | _impl->AddAdEvent(action, adType, ToStdString(adSdkName), ToStdString(adPlacement), ToStdString(CustomFields.ToString()), mergeFields);
464 | }
465 | else
466 | {
467 | GA_NOT_SUPPORTED_WARNING();
468 | }
469 | }
470 |
471 | void UGameAnalytics::AddAdEventWithDuration(EGAAdAction Action, EGAAdType AdType, const FString& AdSdkName, const FString& AdPlacement, int64 Duration, const FGACustomFields CustomFields, bool MergeFields)
472 | {
473 | if(_impl)
474 | {
475 | _impl->AddAdEventWithDuration(Action, AdType, ToStdString(AdSdkName), ToStdString(AdPlacement), Duration, ToStdString(CustomFields.ToString()), MergeFields);
476 | }
477 | else
478 | {
479 | GA_NOT_SUPPORTED_WARNING();
480 | }
481 | }
482 |
483 | void UGameAnalytics::AddAdEventWithReason(EGAAdAction Action, EGAAdType AdType, const FString& AdSdkName, const FString& AdPlacement, EGAAdError Reason, const FGACustomFields CustomFields, bool MergeFields)
484 | {
485 | if(_impl)
486 | {
487 | _impl->AddAdEventWithReason(Action, AdType, ToStdString(AdSdkName), ToStdString(AdPlacement), Reason, ToStdString(CustomFields.ToString()), MergeFields);
488 | }
489 | else
490 | {
491 | GA_NOT_SUPPORTED_WARNING();
492 | }
493 | }
494 |
495 | void UGameAnalytics::SetEnabledInfoLog(bool flag)
496 | {
497 | if(_impl)
498 | {
499 | _impl->SetInfoLog(flag);
500 | }
501 | else
502 | {
503 | GA_NOT_SUPPORTED_WARNING();
504 | }
505 | }
506 |
507 | void UGameAnalytics::SetEnabledVerboseLog(bool flag)
508 | {
509 | if(_impl)
510 | {
511 | _impl->SetVerboseLog(flag);
512 | }
513 | else
514 | {
515 | GA_NOT_SUPPORTED_WARNING();
516 | }
517 | }
518 |
519 | void UGameAnalytics::SetEnabledManualSessionHandling(bool flag)
520 | {
521 | if(_impl)
522 | {
523 | _impl->SetEnabledManualSessionHandling(flag);
524 | }
525 | else
526 | {
527 | GA_NOT_SUPPORTED_WARNING();
528 | }
529 | }
530 |
531 | void UGameAnalytics::SetEnabledErrorReporting(bool flag)
532 | {
533 | if(_impl)
534 | {
535 | _impl->SetEnabledErrorReporting(flag);
536 | }
537 | else
538 | {
539 | GA_NOT_SUPPORTED_WARNING();
540 | }
541 | }
542 |
543 | void UGameAnalytics::SetEnabledEventSubmission(bool flag)
544 | {
545 | if(_impl)
546 | {
547 | _impl->SetEnabledEventSubmission(flag, false);
548 | }
549 | else
550 | {
551 | GA_NOT_SUPPORTED_WARNING();
552 | }
553 | }
554 |
555 | void UGameAnalytics::SetCustomDimension01(FString const& customDimension)
556 | {
557 | if(_impl)
558 | {
559 | _impl->SetCustomDimension01(ToStdString(customDimension));
560 | }
561 | else
562 | {
563 | GA_NOT_SUPPORTED_WARNING();
564 | }
565 | }
566 |
567 | void UGameAnalytics::SetCustomDimension02(FString const& customDimension)
568 | {
569 | if(_impl)
570 | {
571 | _impl->SetCustomDimension02(ToStdString(customDimension));
572 | }
573 | else
574 | {
575 | GA_NOT_SUPPORTED_WARNING();
576 | }
577 | }
578 |
579 | void UGameAnalytics::SetCustomDimension03(FString const& customDimension)
580 | {
581 | if(_impl)
582 | {
583 | _impl->SetCustomDimension03(ToStdString(customDimension));
584 | }
585 | else
586 | {
587 | GA_NOT_SUPPORTED_WARNING();
588 | }
589 | }
590 |
591 | FString UGameAnalytics::GetUserId()
592 | {
593 | if (_impl)
594 | {
595 | FString uid = ToFString(_impl->GetUserId());
596 | return uid;
597 | }
598 | else
599 | {
600 | GA_NOT_SUPPORTED_WARNING();
601 | return TEXT("");
602 | }
603 | }
604 |
605 | FString UGameAnalytics::GetExternalUserId()
606 | {
607 | if (_impl)
608 | {
609 | FString uid = ToFString(_impl->GetExternalUserId());
610 | return uid;
611 | }
612 | else
613 | {
614 | GA_NOT_SUPPORTED_WARNING();
615 | return TEXT("");
616 | }
617 | }
618 |
619 | void UGameAnalytics::StartSession()
620 | {
621 | if(_impl)
622 | {
623 | _impl->StartSession();
624 | }
625 | else
626 | {
627 | GA_NOT_SUPPORTED_WARNING();
628 | }
629 | }
630 |
631 | void UGameAnalytics::EndSession()
632 | {
633 | if(_impl)
634 | {
635 | _impl->EndSession();
636 | }
637 | else
638 | {
639 | GA_NOT_SUPPORTED_WARNING();
640 | }
641 | }
642 |
643 | void UGameAnalytics::OnQuit()
644 | {
645 | if(_impl)
646 | {
647 | _impl->OnQuit();
648 | }
649 | else
650 | {
651 | GA_NOT_SUPPORTED_WARNING();
652 | }
653 | }
654 |
655 | FString UGameAnalytics::GetRemoteConfigsValueAsString(FString const& key, FString const& defaultValue)
656 | {
657 | if(_impl)
658 | {
659 | std::string val = _impl->GetRemoteConfigsValueAsString(ToStdString(key), ToStdString(defaultValue));
660 | return ToFString(val);
661 | }
662 | else
663 | {
664 | GA_NOT_SUPPORTED_WARNING();
665 | return defaultValue;
666 | }
667 | }
668 |
669 | TSharedPtr UGameAnalytics::GetRemoteConfigsValueAsJSON(FString const& key)
670 | {
671 | TSharedPtr Json(new FJsonObject);
672 |
673 | if(_impl)
674 | {
675 | FString JsonString = GetRemoteConfigsValueAsString(key);
676 | TSharedRef> Reader = FJsonStringReader::Create(JsonString);
677 | FJsonSerializer::Deserialize(Reader, Json);
678 | }
679 | else
680 | {
681 | GA_NOT_SUPPORTED_WARNING();
682 | }
683 |
684 | return Json;
685 | }
686 |
687 |
688 | bool UGameAnalytics::IsRemoteConfigsReady()
689 | {
690 | if(_impl)
691 | {
692 | return _impl->IsRemoteConfigsReady();
693 | }
694 | else
695 | {
696 | GA_NOT_SUPPORTED_WARNING();
697 | return false;
698 | }
699 | }
700 |
701 | FString UGameAnalytics::GetRemoteConfigsContentAsString()
702 | {
703 | if(_impl)
704 | {
705 | std::string remoteConfigs = _impl->GetRemoteConfigsContentAsString();
706 | return ToFString(remoteConfigs);
707 | }
708 | else
709 | {
710 | GA_NOT_SUPPORTED_WARNING();
711 | return TEXT("");
712 | }
713 | }
714 |
715 | FString UGameAnalytics::GetABTestingId()
716 | {
717 | if(_impl)
718 | {
719 | std::string abTestingId = _impl->GetABTestingId();
720 | return ToFString(abTestingId);
721 | }
722 | else
723 | {
724 | GA_NOT_SUPPORTED_WARNING();
725 | return TEXT("");
726 | }
727 | }
728 |
729 | FString UGameAnalytics::GetABTestingVariantId()
730 | {
731 | if(_impl)
732 | {
733 | std::string abTestingVarId = _impl->GetABTestingVariantId();
734 | return ToFString(abTestingVarId);
735 | }
736 | else
737 | {
738 | GA_NOT_SUPPORTED_WARNING();
739 | return TEXT("");
740 | }
741 | }
742 |
743 | void UGameAnalytics::EnableSDKInitEvent(bool value)
744 | {
745 | if(_impl)
746 | {
747 | _impl->EnableSDKInitEvent(value);
748 | }
749 | else
750 | {
751 | GA_NOT_SUPPORTED_WARNING();
752 | }
753 | }
754 |
755 | void UGameAnalytics::EnableFpsHistogram(bool value)
756 | {
757 | if(_impl)
758 | {
759 | if(value && !_performanceTracker)
760 | {
761 | _performanceTracker = NewObject();
762 | _performanceTracker->AddToRoot();
763 | }
764 |
765 | if(_performanceTracker)
766 | {
767 | _performanceTracker->EnableFPSTracking = value;
768 | }
769 |
770 | gameanalytics::FPSTracker tracker = [this]() -> float
771 | {
772 | return _performanceTracker->GetAvgFps();
773 | };
774 |
775 | _impl->EnableFpsHistogram(tracker, value);
776 | }
777 | else
778 | {
779 | GA_NOT_SUPPORTED_WARNING();
780 | }
781 | }
782 |
783 | void UGameAnalytics::EnableMemoryHistogram(bool value)
784 | {
785 | if(_impl)
786 | {
787 | _impl->EnableMemoryHistogram(value);
788 | }
789 | else
790 | {
791 | GA_NOT_SUPPORTED_WARNING();
792 | }
793 | }
794 |
795 | void UGameAnalytics::EnableHealthHardwareInfo(bool value)
796 | {
797 | if(_impl)
798 | {
799 | _impl->EnableHealthHardwareInfo(value);
800 | }
801 | else
802 | {
803 | GA_NOT_SUPPORTED_WARNING();
804 | }
805 | }
806 |
807 | void UGameAnalytics::EnableAdvertisingId(bool value)
808 | {
809 | if(_impl)
810 | {
811 | _impl->EnableAdvertisingId(value);
812 | }
813 | else
814 | {
815 | GA_NOT_SUPPORTED_WARNING();
816 | }
817 | }
818 |
819 | int64 UGameAnalytics::GetElapsedSessionTime()
820 | {
821 | if (_impl)
822 | {
823 | return _impl->GetElapsedSessionTime();
824 | }
825 | else
826 | {
827 | GA_NOT_SUPPORTED_WARNING();
828 | return 0;
829 | }
830 | }
831 |
832 | int64 UGameAnalytics::GetElapsedTimeFromAllSessions()
833 | {
834 | if (_impl)
835 | {
836 | return _impl->GetElapsedTimeFromAllSessions();
837 | }
838 | else
839 | {
840 | GA_NOT_SUPPORTED_WARNING();
841 | return 0;
842 | }
843 | }
844 |
845 | void UGameAnalytics::SetWritablePath(FString const& path)
846 | {
847 | if(_impl)
848 | {
849 | _impl->SetWritablePath(ToStdString(path));
850 | }
851 | else
852 | {
853 | GA_NOT_SUPPORTED_WARNING();
854 | }
855 | }
856 |
857 |
--------------------------------------------------------------------------------
/GameAnalytics/Source/GameAnalytics/Private/IOS/GAWrapperIOS.mm:
--------------------------------------------------------------------------------
1 | #import "GameAnalytics/GA-SDK-IOS/GameAnalytics.h"
2 | #import "GAWrapperIOS.h"
3 |
4 |
5 | // Objective-C++ wrapper for FPSTracker
6 | @interface GAHealthMetricsProvider : NSObject
7 | {
8 | std::function fpsTracker;
9 | }
10 | - (instancetype)initWithFPSTracker:(const std::function&)tracker;
11 | @end
12 |
13 | @implementation GAHealthMetricsProvider
14 | - (instancetype)initWithFPSTracker:(const std::function&)tracker {
15 | self = [super init];
16 | if (self) {
17 | fpsTracker = tracker;
18 | }
19 | return self;
20 | }
21 | - (double)provideCurrentFPS {
22 | if (fpsTracker) {
23 | return (double)fpsTracker();
24 | }
25 | return -1.0;
26 | }
27 | @end
28 |
29 | namespace gameanalytics
30 | {
31 | NSString* ToNSString(std::string const& str)
32 | {
33 | NSString *s = (!str.empty()) ? [NSString stringWithUTF8String:str.c_str()] : nil;
34 | return s;
35 | }
36 |
37 | std::string FromNSString(NSString* str)
38 | {
39 | std::string s = (str != nil) ? [str UTF8String] : "";
40 | return s;
41 | }
42 |
43 | void GAWrapperIOS::SetAvailableCustomDimensions01(const std::vector& list)
44 | {
45 | NSMutableArray * tmpary = [[NSMutableArray alloc] initWithCapacity: list.size()];
46 | for (const std::string& s : list)
47 | {
48 | [tmpary addObject: [NSString stringWithUTF8String: s.c_str()]];
49 | }
50 | NSArray *list_array = tmpary;
51 | [GameAnalytics configureAvailableCustomDimensions01:list_array];
52 | }
53 |
54 | void GAWrapperIOS::SetAvailableCustomDimensions02(const std::vector& list) {
55 | NSMutableArray * tmpary = [[NSMutableArray alloc] initWithCapacity: list.size()];
56 | for (const std::string& s : list)
57 | {
58 | [tmpary addObject: [NSString stringWithUTF8String: s.c_str()]];
59 | }
60 | NSArray *list_array = tmpary;
61 | [GameAnalytics configureAvailableCustomDimensions02:list_array];
62 | }
63 |
64 | void GAWrapperIOS::SetAvailableCustomDimensions03(const std::vector& list) {
65 | NSMutableArray * tmpary = [[NSMutableArray alloc] initWithCapacity: list.size()];
66 | for (const std::string& s : list)
67 | {
68 | [tmpary addObject: [NSString stringWithUTF8String: s.c_str()]];
69 | }
70 | NSArray *list_array = tmpary;
71 | [GameAnalytics configureAvailableCustomDimensions03:list_array];
72 | }
73 |
74 | void GAWrapperIOS::SetAvailableResourceCurrencies(const std::vector& list) {
75 | NSMutableArray * tmpary = [[NSMutableArray alloc] initWithCapacity: list.size()];
76 | for (const std::string& s : list)
77 | {
78 | [tmpary addObject: [NSString stringWithUTF8String: s.c_str()]];
79 | }
80 | NSArray *list_array = tmpary;
81 | [GameAnalytics configureAvailableResourceCurrencies:list_array];
82 | }
83 |
84 | void GAWrapperIOS::SetAvailableResourceItemTypes(const std::vector& list) {
85 | NSMutableArray * tmpary = [[NSMutableArray alloc] initWithCapacity: list.size()];
86 | for (const std::string& s : list)
87 | {
88 | [tmpary addObject: [NSString stringWithUTF8String: s.c_str()]];
89 | }
90 | NSArray *list_array = tmpary;
91 | [GameAnalytics configureAvailableResourceItemTypes:list_array];
92 | }
93 |
94 | void GAWrapperIOS::SetBuild(std::string const& build) {
95 | NSString *buildString = ToNSString(build);
96 | [GameAnalytics configureBuild:buildString];
97 | }
98 |
99 | void GAWrapperIOS::SetAutoDetectAppVersion(bool flag) {
100 | [GameAnalytics configureAutoDetectAppVersion:flag];
101 | }
102 |
103 | void GAWrapperIOS::SetCustomUserId(std::string const& userId) {
104 | NSString *userIdString = ToNSString(userId);
105 | [GameAnalytics configureUserId:userIdString];
106 | }
107 |
108 | void GAWrapperIOS::SetGameEngineVersion(std::string const& gameEngineSdkVersion) {
109 | NSString *gameEngineSdkVersionString = ToNSString(gameEngineSdkVersion);
110 | [GameAnalytics configureSdkVersion:gameEngineSdkVersionString];
111 | }
112 |
113 | void GAWrapperIOS::SetSDKVersion(std::string const& sdkVersion) {
114 | NSString *sdkVersionString = ToNSString(sdkVersion);
115 | [GameAnalytics configureSdkVersion:sdkVersionString];
116 | }
117 |
118 | void GAWrapperIOS::SetGlobalCustomEventFields(std::string const& fields) {
119 |
120 | NSString *jsonString = ToNSString(fields);
121 | NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
122 |
123 | NSError *error = nil;
124 | NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
125 |
126 | if (!error)
127 | {
128 | [GameAnalytics setGlobalCustomEventFields:jsonDict];
129 | }
130 | }
131 |
132 | void GAWrapperIOS::Initialize(std::string const& gameKey, std::string const& gameSecret) {
133 | NSString *gameKeyString = ToNSString(gameKey);
134 | NSString *gameSecretString = ToNSString(gameSecret);
135 |
136 | [GameAnalytics initializeWithGameKey:gameKeyString gameSecret:gameSecretString];
137 | }
138 |
139 | void GAWrapperIOS::AddBusinessEvent(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& receipt, std::string const& fields, bool mergeFields) {
140 | NSString *currencyString = ToNSString(currency);
141 | NSInteger amountInteger = (NSInteger)amount;
142 | NSString *itemTypeString = ToNSString(itemType);
143 | NSString *itemIdString = ToNSString(itemId);
144 | NSString *cartTypeString = ToNSString(cartType);
145 | NSString *receiptString = ToNSString(receipt);
146 | NSString *fieldsString = ToNSString(fields);
147 | NSDictionary *fields_dict = nil;
148 | if (fieldsString) {
149 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
150 | }
151 |
152 | [GameAnalytics addBusinessEventWithCurrency:currencyString
153 | amount:amountInteger
154 | itemType:itemTypeString
155 | itemId:itemIdString
156 | cartType:cartTypeString
157 | receipt:receiptString
158 | customFields:fields_dict
159 | mergeFields:mergeFields];
160 | }
161 |
162 | void GAWrapperIOS::AddBusinessEventWithReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& receipt, std::string const& store, std::string const& signature, std::string const& fields, bool mergeFields)
163 | {
164 | return AddBusinessEvent(currency, amount, itemType, itemId, cartType, receipt, fields, mergeFields);
165 | }
166 |
167 | void GAWrapperIOS::AddBusinessEventAndAutoFetchReceipt(std::string const& currency, int amount, std::string const& itemType, std::string const& itemId, std::string const& cartType, std::string const& fields, bool mergeFields) {
168 | NSString *currencyString = ToNSString(currency);
169 | NSInteger amountInteger = (NSInteger)amount;
170 | NSString *itemTypeString = ToNSString(itemType);
171 | NSString *itemIdString = ToNSString(itemId);
172 | NSString *cartTypeString = ToNSString(cartType);
173 | NSString *fieldsString = ToNSString(fields);
174 | NSDictionary *fields_dict = nil;
175 | if (fieldsString) {
176 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
177 | }
178 |
179 | [GameAnalytics addBusinessEventWithCurrency:currencyString
180 | amount:amountInteger
181 | itemType:itemTypeString
182 | itemId:itemIdString
183 | cartType:cartTypeString
184 | autoFetchReceipt:true
185 | customFields:fields_dict
186 | mergeFields:mergeFields];
187 | }
188 |
189 | void GAWrapperIOS::AddResourceEvent(EGAResourceFlowType flowType, std::string const& currency, float amount, std::string const& itemType, std::string const& itemId, std::string const& fields, bool mergeFields) {
190 | NSString *currencyString = ToNSString(currency);
191 | NSNumber* amountNumber = [NSNumber numberWithFloat:amount];;
192 | NSString *itemTypeString = ToNSString(itemType);
193 | NSString *itemIdString = ToNSString(itemId);
194 | NSString *fieldsString = ToNSString(fields);
195 | NSDictionary *fields_dict = nil;
196 | if (fieldsString) {
197 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
198 | }
199 |
200 | [GameAnalytics addResourceEventWithFlowType:(GAResourceFlowType)flowType
201 | currency:currencyString
202 | amount:amountNumber
203 | itemType:itemTypeString
204 | itemId:itemIdString
205 | customFields:fields_dict
206 | mergeFields:mergeFields];
207 | }
208 |
209 | void GAWrapperIOS::AddProgressionEvent(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, std::string const& fields, bool mergeFields) {
210 | NSString *progression01String = ToNSString(progression01);
211 | NSString *progression02String = ToNSString(progression02);
212 | NSString *progression03String = ToNSString(progression03);
213 | NSString *fieldsString = ToNSString(fields);
214 | NSDictionary *fields_dict = nil;
215 | if (fieldsString) {
216 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
217 | }
218 |
219 | [GameAnalytics addProgressionEventWithProgressionStatus:(GAProgressionStatus)progressionStatus
220 | progression01:progression01String
221 | progression02:progression02String
222 | progression03:progression03String
223 | customFields:fields_dict
224 | mergeFields:mergeFields];
225 | }
226 |
227 | void GAWrapperIOS::AddProgressionEventWithScore(EGAProgressionStatus progressionStatus, std::string const& progression01, std::string const& progression02, std::string const& progression03, int score, std::string const& fields, bool mergeFields) {
228 | NSString *progression01String = ToNSString(progression01);
229 | NSString *progression02String = ToNSString(progression02);
230 | NSString *progression03String = ToNSString(progression03);
231 | NSString *fieldsString = ToNSString(fields);
232 | NSDictionary *fields_dict = nil;
233 | if (fieldsString) {
234 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
235 | }
236 |
237 | [GameAnalytics addProgressionEventWithProgressionStatus:(GAProgressionStatus)progressionStatus
238 | progression01:progression01String
239 | progression02:progression02String
240 | progression03:progression03String
241 | score:score
242 | customFields:fields_dict
243 | mergeFields:mergeFields];
244 | }
245 |
246 | void GAWrapperIOS::AddDesignEvent(std::string const& eventId, std::string const& fields, bool mergeFields) {
247 | NSString *eventIdString = ToNSString(eventId);
248 | NSString *fieldsString = ToNSString(fields);
249 | NSDictionary *fields_dict = nil;
250 | if (fieldsString) {
251 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
252 | }
253 |
254 | [GameAnalytics addDesignEventWithEventId:eventIdString value:nil customFields:fields_dict mergeFields:mergeFields];
255 | }
256 |
257 | void GAWrapperIOS::AddDesignEventWithValue(std::string const& eventId, float value, std::string const& fields, bool mergeFields) {
258 | NSString *eventIdString = ToNSString(eventId);
259 | NSNumber *valueNumber = [NSNumber numberWithFloat:value];
260 | NSString *fieldsString = ToNSString(fields);
261 | NSDictionary *fields_dict = nil;
262 | if (fieldsString) {
263 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
264 | }
265 |
266 | [GameAnalytics addDesignEventWithEventId:eventIdString value:valueNumber customFields:fields_dict mergeFields:mergeFields];
267 | }
268 |
269 | void GAWrapperIOS::AddErrorEvent(EGAErrorSeverity severity, std::string const& message, std::string const& fields, bool mergeFields) {
270 | NSString *messageString = ToNSString(message);
271 | NSString *fieldsString = ToNSString(fields);
272 | NSDictionary *fields_dict = nil;
273 | if (fieldsString) {
274 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
275 | }
276 |
277 | [GameAnalytics addErrorEventWithSeverity:(GAErrorSeverity)severity message:messageString customFields:fields_dict mergeFields:mergeFields];
278 | }
279 |
280 | void GAWrapperIOS::AddAdEvent(EGAAdAction action, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, std::string const& fields, bool mergeFields) {
281 | NSString *adSdkNameString = ToNSString(adSdkName);
282 | NSString *adPlacementString = ToNSString(adPlacement);
283 | NSString *fieldsString = ToNSString(fields);
284 | NSDictionary *fields_dict = nil;
285 | if (fieldsString) {
286 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
287 | }
288 | [GameAnalytics addAdEventWithAction:(GAAdAction)action
289 | adType:(GAAdType)adType
290 | adSdkName:adSdkNameString
291 | adPlacement:adPlacementString
292 | customFields:fields_dict
293 | mergeFields:mergeFields];
294 | }
295 | void GAWrapperIOS::AddAdEventWithDuration(EGAAdAction action, EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, int64_t duration, std::string const& fields, bool mergeFields) {
296 | NSString *adSdkNameString = ToNSString(adSdkName);
297 | NSString *adPlacementString = ToNSString(adPlacement);
298 | NSString *fieldsString = ToNSString(fields);
299 | NSDictionary *fields_dict = nil;
300 | if (fieldsString) {
301 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
302 | }
303 | [GameAnalytics addAdEventWithAction:(GAAdAction)action
304 | adType:(GAAdType)adType
305 | adSdkName:adSdkNameString
306 | adPlacement:adPlacementString
307 | duration:(NSInteger)duration
308 | customFields:fields_dict
309 | mergeFields:mergeFields];
310 | }
311 |
312 | void GAWrapperIOS::AddAdEventWithReason(::EGAAdAction action, ::EGAAdType adType, std::string const& adSdkName, std::string const& adPlacement, ::EGAAdError noAdReason, std::string const& fields, bool mergeFields) {
313 | NSString *adSdkNameString = ToNSString(adSdkName);
314 | NSString *adPlacementString = ToNSString(adPlacement);
315 | NSString *fieldsString = ToNSString(fields);
316 | NSDictionary *fields_dict = nil;
317 | if (fieldsString) {
318 | fields_dict = [NSJSONSerialization JSONObjectWithData:[fieldsString dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
319 | }
320 | [GameAnalytics addAdEventWithAction:(GAAdAction)action
321 | adType:(GAAdType)adType
322 | adSdkName:adSdkNameString
323 | adPlacement:adPlacementString
324 | noAdReason:(GAAdError)noAdReason
325 | customFields:fields_dict
326 | mergeFields:mergeFields];
327 | }
328 |
329 | void GAWrapperIOS::SetInfoLog(bool flag) {
330 | [GameAnalytics setEnabledInfoLog:flag];
331 | }
332 |
333 | void GAWrapperIOS::SetVerboseLog(bool flag) {
334 | [GameAnalytics setEnabledVerboseLog:flag];
335 | }
336 |
337 | void GAWrapperIOS::SetEnabledManualSessionHandling(bool flag) {
338 | [GameAnalytics setEnabledManualSessionHandling:flag];
339 | }
340 |
341 | void GAWrapperIOS::SetEnabledErrorReporting(bool flag) {
342 | [GameAnalytics setEnabledErrorReporting:flag];
343 | }
344 |
345 | void GAWrapperIOS::SetEnabledEventSubmission(bool flag, bool doOfflineCache) {
346 | [GameAnalytics setEnabledEventSubmission:flag];
347 | }
348 |
349 | void GAWrapperIOS::SetCustomDimension01(std::string const& customDimension) {
350 | NSString *customDimensionString = ToNSString(customDimension);
351 | [GameAnalytics setCustomDimension01:customDimensionString];
352 | }
353 |
354 | void GAWrapperIOS::SetCustomDimension02(std::string const& customDimension) {
355 | NSString *customDimensionString = ToNSString(customDimension);
356 | [GameAnalytics setCustomDimension02:customDimensionString];
357 | }
358 |
359 | void GAWrapperIOS::SetCustomDimension03(std::string const& customDimension) {
360 | NSString *customDimensionString = ToNSString(customDimension);
361 | [GameAnalytics setCustomDimension03:customDimensionString];
362 | }
363 |
364 | void GAWrapperIOS::StartSession() {
365 | [GameAnalytics startSession];
366 | }
367 |
368 | void GAWrapperIOS::EndSession() {
369 | [GameAnalytics endSession];
370 | }
371 |
372 | std::string GAWrapperIOS::GetRemoteConfigsValueAsString(std::string const& key, std::string const& defaultValue) {
373 | NSString *keyString = ToNSString(key);
374 | NSString *result = [GameAnalytics getRemoteConfigsValueAsString:keyString];
375 |
376 | std::string s = result != nil ? [result UTF8String] : defaultValue;
377 | return s;
378 | }
379 |
380 | double GAWrapperIOS::GetRemoteConfigsValueAsNumber(std::string const& key, double defaultValue) {
381 | return defaultValue;
382 | }
383 |
384 | std::string GAWrapperIOS::GetRemoteConfigsValueAsJson(std::string const& key) {
385 | return "";
386 | }
387 |
388 | bool GAWrapperIOS::IsRemoteConfigsReady() {
389 | return [GameAnalytics isRemoteConfigsReady] ? true : false;
390 | }
391 |
392 | std::string GAWrapperIOS::GetRemoteConfigsContentAsString() {
393 | NSString *result = [GameAnalytics getRemoteConfigsContentAsString];
394 |
395 | std::string s = FromNSString(result);
396 | return s;
397 | }
398 |
399 | std::string GAWrapperIOS::GetUserId() {
400 | NSString* uid = [GameAnalytics getUserId];
401 | return FromNSString(uid);
402 | }
403 |
404 | std::string GAWrapperIOS::GetExternalUserId() {
405 | NSString* uid = [GameAnalytics getExternalUserId];
406 | return FromNSString(uid);
407 | }
408 |
409 | void GAWrapperIOS::SetExternalUserId(std::string const& id) {
410 | NSString* uid = ToNSString(id);
411 | [GameAnalytics configureExternalUserId:uid];
412 | }
413 |
414 | std::string GAWrapperIOS::GetABTestingId() {
415 | NSString *result = [GameAnalytics getABTestingId];
416 |
417 | std::string s = FromNSString(result);
418 | return s;
419 | }
420 |
421 | std::string GAWrapperIOS::GetABTestingVariantId() {
422 | NSString *result = [GameAnalytics getABTestingVariantId];
423 |
424 | std::string s = FromNSString(result);
425 | return s;
426 | }
427 |
428 | void GAWrapperIOS::EnableAdvertisingId(bool value)
429 | {
430 | // Note: This method is deprecated and has no effect.
431 | }
432 |
433 | void GAWrapperIOS::EnableSDKInitEvent(bool value)
434 | {
435 | [GameAnalytics enableSDKInitEvent:value];
436 | }
437 |
438 |
439 |
440 | void GAWrapperIOS::EnableFpsHistogram(FPSTracker tracker, bool value)
441 | {
442 | if (value)
443 | {
444 | // Always create a new delegate with the latest tracker
445 | GAHealthMetricsProvider *provider = [[GAHealthMetricsProvider alloc] initWithFPSTracker:tracker];
446 | [GameAnalytics setHealthMetricsDelegate:provider];
447 | }
448 | else
449 | {
450 | [GameAnalytics setHealthMetricsDelegate:nil];
451 | }
452 |
453 | [GameAnalytics enableFpsHistogram:value];
454 | }
455 |
456 | int64_t GAWrapperIOS::GetElapsedSessionTime()
457 | {
458 | // Returns the elapsed time for the current session in seconds
459 | return (int64_t)[GameAnalytics getElapsedSessionTime];
460 | }
461 |
462 | int64_t GAWrapperIOS::GetElapsedTimeForPreviousSession()
463 | {
464 | // Returns the elapsed time for the previous session in seconds
465 | return (int64_t)[GameAnalytics getElapsedTimeForPreviousSession];
466 | }
467 |
468 | int64_t GAWrapperIOS::GetElapsedTimeFromAllSessions()
469 | {
470 | // Returns the total elapsed time from all sessions in seconds
471 | return (int64_t)[GameAnalytics getElapsedTimeFromAllSessions];
472 | }
473 |
474 | void GAWrapperIOS::EnableMemoryHistogram(bool value)
475 | {
476 | [GameAnalytics enableMemoryHistogram:value];
477 | }
478 |
479 | void GAWrapperIOS::EnableHealthHardwareInfo(bool value)
480 | {
481 | [GameAnalytics enableHealthHardwareInfo:value];
482 | }
483 |
484 | void GAWrapperIOS::OnQuit()
485 | {
486 |
487 | }
488 |
489 | void GAWrapperIOS::SetWritablePath(std::string const& path)
490 | {
491 | (void)path;
492 | }
493 |
494 | }
495 |
--------------------------------------------------------------------------------