Unreal Engine
iOS Requirements
- ~v1.1.1
- v1.2.0~
- Xcode 15.X
- AppGuard for iOS SDK v1.10.1.3 or later
- Xcode 15.4 or later
- Minimum OS 12.0 or later
- AppGuard for iOS SDK v1.10.2.0 or later
A Minimum OS bug in Xcode versions earlier than 15.4 exists.
This bug has been resolved starting from Xcode version 15.4.
Unreal Plugin Overview
This document explains how to apply the AppGuard SDK in Unreal Engine 4 and 5 environments using the plugin method, which is easier than traditional integration methods.
Download and Install Unreal Plugin
To install the Unreal Plugin and set up your project in Unreal Engine 4 or 5, follow these steps:
-
Access the AppGuard Manager server and select Download > Unreal Plugins to download the latest version.
-
In the downloaded
AppGuardUnrealPlugin.zipfile, you'll find a folder named /AppGuardSDK. Copy this folder to the Project/Plugins/ directory. -
Open the
APPNAME.Build.csfile in the Project/Source/ProjectName/ path and add"AppGuardSDK"as shown below to install AppGuard SDK into your Unreal project.
PublicDependencyModuleNames.AddRange(new string[]
{
"Core", "CoreUObject", "Engine", "InputCore", "AppGuardSDK"
});
Download and Configure AppGuard Config Files
-
Access the AppGuard Manager server and select Applying Security > Download > CHAPTER 2. nProtect AppGuard CONFIG File Download > CONFIG FILE DOWNLOAD to download the files.
-
After extracting the downloaded config file, you will find four files:
appguard,appguard.crt,appguard.mf, andappguard106000. -
Copy these four files to the following path:
Copy To: Project/Binaries/IOS/Payload/APPNAME.app/
If you are using Modernized Xcode options supported in UE5.2 or later,
you must copy the AppGuard Config files into Unreal Project/XXXXProject/Binaries/IOS/XXXXX.app/.
If you have never performed an iOS build from Unreal Editor, the Project/Binaries/IOS folder might not exist. In this case, perform an iOS build once before proceeding with the above steps.
Applying AppGuardSDK Unreal Plugin
Register Callback in Delegate and Call AppGuard Initialization Function
To receive event notifications when a security policy violation is detected during app execution, register a callback in the Delegate. Also, you must call the UAppGuardSDKBlueprintLibrary::Start(); function to initialize AppGuard. This function should be called at the earliest point when the app starts.
class ASampleProjectGameMode : public AGameModeBase
{
GENERATED_BODY()
//. Add
virtual void InitGame(const FString& MapName,
const FString& Options,
FString& ErrorMessage) override;
void OnS2AuthCompleted(int value, const FString& data);
void OnDetected(int value);
//. Add
public:
ASampleProjectGameMode();
};
#include "AppGuardSDKPlugin.h"
#include "AppGuardSDKBlueprintLibrary.h"
void ASampleProjectGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) {
//. Register callback function for security detection
FAppGuardSDKModule::OnDetected.AddUObject(this, &ASampleProject::OnDetected); // Register callback
//. Register callback function for server authentication
FAppGuardSDKModule::OnS2AuthCompleted.AddUObject(this, &ASampleProject::OnS2AuthCompleted);
//. Initialize AppGuardCore.framework to use AppGuard
UAppGuardSDKBlueprintLibrary::Start();
}
/* Sample callback function for security detection */
void ASampleProjectGameMode::OnDetected (int data) {
bool killed = data > 0;
int code = data > 0 ? data : data * -1;
/*
If the value of data is positive, AppGuard will close after 30 seconds.
Use the sample code below to display this message to the user on the appropriate screen.
*/
if (killed) {
//. Show an exit notification to inform the user that the game will close.
//. The exit notification should be configured so that the app closes when the OK button is clicked.
}
}
/* Sample callback function for server authentication */
void ASampleProjectGameMode::OnS2AuthCompleted (int value, FString data) {
//. Refer to the [Server Authentication Application] stage for server authentication callback implementation.
}
For service releases, make sure to remove any log output statements from the above security detection and server authentication callback functions.
Setting UserID
To send a User ID to the log server in case of a policy violation detection, you can use the SetUserId() method.
As shown in the sample code below, pass the session's user ID as an FString in the userID field.
#include "AppGuardSDKPlugin.h"
#include "AppGuardSDKBlueprintLibrary.h"
UAppGuardSDKBlueprintLibrary::SetUserId(TEXT("userID"));
Applying Server Authentication (Optional)
This section is only relevant if server authentication is being used. If not, it can be ignored.
Implementing the Callback Function for Server Authentication
Server authentication-related callbacks are triggered through the OnS2AuthCompleted() callback method, which was registered in the Register Callback in Delegate and Call AppGuard Initialization Function section.
The following sample code shows how the server authentication status results are communicated via the OnS2AuthCompleted() callback method.
#include "AppGuardSDKPlugin.h"
#include "AppGuardSDKBlueprintLibrary.h"
// Sample callback function for server authentication
void ASampleProjectGameMode::OnS2AuthCompleted (int value, FString data)
{
switch (value)
{
case AppGuardEventType::S2Auth::S2AUTH_RESULT_SUCCESS:
/*
Server authentication was successful, and the authentication process has been completed.
*/
break;
case AppGuardEventType::S2Auth::S2AUTH_RESULT_RETRY:
/*
Server authentication failed and a retry will be attempted. This could be due to a temporary client network or server issue.
The retry process will continue for up to 3 minutes based on internal mechanisms.
*/
break;
case AppGuardEventType::S2Auth::S2AUTH_RESULT_FAIL:
/*
Server authentication has completely failed, and no further attempts will be made.
*/
break;
}
}
When you call the UAppGuardSDKBlueprintLibrary::SetUniqueClientId() method as described in the Start Server Authentication section,
the AppGuard security module will attempt server authentication and send one of the three status codes via the callback method, as shown in the sample code above.
For service releases, make sure to remove any log output statements from the above server authentication callback function.
Start Server Authentication
To start server authentication from the client, use the UniqueClientID received from the server and pass it to the method as shown in the following sample code.
#include "AppGuardSDKPlugin.h"
#include "AppGuardSDKBlueprintLibrary.h"
UAppGuardSDKBlueprintLibrary::SetUniqueClientId(TEXT("Formatted-Unique-Client-Id", 180));
For the formatting rules and creation method for the Formatted-Unique-Client-Id, refer to [Key API Documentation].
Applying AppGuard SDK Privacy Manifests (UE4, UE5)
- ~v1.10.1.3
- v1.10.2.0~
This guide requires AppGuard SDK version v1.10.1.3 or later to apply Privacy Manifests.
The Unreal Plugin includes the AppGuard SDK, which is distributed under the name AppGuardCore.framework.
AppGuardCore.framework is distributed as a .zip file located inside Unreal Project/Plugins/AppGuardSDK/Source/AppGuardSDK/Libs/IOS/.
AppGuardCore.framework is linked to the project as Do Not Embed and built.
if(Target.Platform == UnrealTargetPlatform.IOS)
{
string LibPath = Path.Combine(ModuleDirectory, "Libs/IOS");
PrivateIncludePaths.Add("AppGuardSDK/Private/IOS");
PublicFrameworks.Add("Security");
PublicAdditionalFrameworks.Add(
new Framework(
"AppGuardCore",
Path.Combine(LibPath, "AppGuardCore.framework.zip"),
""
)
);
string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory,
Target.RelativeEnginePath);
AdditionalPropertiesForReceipt.Add("IOSPlugin",
Path.Combine(PluginPath, "AppGuardSDK_UPL_IOS.xml"));
}
The AppGuardCore.framework module is merged and distributed with the TARGETS that link to the AppGuardCore.framework.
For Apple Privacy Manifests, the PrivacyInfo.xcprivacy of AppGuard SDK must be included in the TARGETS that link AppGuard SDK, and the contents of the AppGuardCore.framework's PrivacyInfo.xcprivacy must be merged with the PrivacyInfo.xcprivacy file of the linked TARGETS.
To specify the AppGuardCore.framework details in PrivacyInfo.xcprivacy, refer to the following guide for the merging process.
-
If your Unreal Project already has a
PrivacyInfo.xcprivacyfile:- Compare the contents of AppGuardCore.framework's
PrivacyInfo.xcprivacyfile with the existingPrivacyInfo.xcprivacyfile to check for missing parts. - If missing parts are found, add and merge them into the existing
PrivacyInfo.xcprivacyfile.
- Compare the contents of AppGuardCore.framework's
-
If your Unreal Project does not have a
PrivacyInfo.xcprivacyfile:-
Copy the content below and create a
PrivacyInfo.xcprivacyfile.
The content below is a merged version of thePrivacyInfo.xcprivacyfile generated in UE5.4 with AppGuardCore.framework'sPrivacyInfo.xcprivacyfile.View the merged
PrivacyInfo.xcprivacyfile from UE5.4 with AppGuardCore.framework'sPrivacyInfo.xcprivacy<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeCrashData</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeGameplayContent</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeProductInteraction</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeUserID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeOtherDataTypes</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<true/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
</array>
</dict>
</plist> -
Copy the created
PrivacyInfo.xcprivacyfile to UnrealProjects/XXXXProject/Binaries/IOS/Payload/XXXXX.app/.
-
For builds using the Modernized Xcode option supported in UE5.2 or later,
you must copy the PrivacyInfo.xcprivacy to Unreal Project/XXXXProject/Binaries/IOS/XXXXX.app/.
Starting from AppGuard for iOS SDK v1.10.1.3, the SDK is distributed as AppGuardCore.framework. This SDK is distributed as a static framework.
Note that AppGuard for iOS SDK v1.10.1.3 only uses NSPrivacyAccessedAPICategoryUserDefaults from the required reason API items in Apple's Privacy Manifest.
For third-party SDKs linked as static frameworks, the same PrivacyInfo.xcprivacy merging process may be required, similar to AppGuard SDK.
This guide requires AppGuard SDK version v1.10.2.0 or later to apply Privacy Manifests.
AppGuard SDK version v1.10.2.0 or later is built and distributed according to Apple's Privacy Manifest requirements, so no merging process is required.
[Apple & Creating a static framework]
To meet Apple's requirements, AppGuard for iOS SDK version v1.10.2.0 or later is created as a static framework and distributed under the name AppGuardCore.xcframework.
Reference for Apple & Creating a static framework: Apple & Creating a static framework
The Unreal Plugin includes the AppGuard SDK, which is distributed under the name AppGuardCore.framework.
AppGuardCore.framework is distributed as a .zip file located inside Unreal Project/Plugins/AppGuardSDK/Source/AppGuardSDK/Libs/IOS/.
AppGuardCore.framework is linked to the project as Do Not Embed and built.
For builds using the Modernized Xcode option supported in UE5.2 or later,
to link AppGuardCore.framework as Embed&Sign, modify the code as shown below:
if(Target.Platform == UnrealTargetPlatform.IOS)
{
string LibPath = Path.Combine(ModuleDirectory, "Libs/IOS");
PrivateIncludePaths.Add("AppGuardSDK/Private/IOS");
PublicFrameworks.Add("Security");
PublicAdditionalFrameworks.Add(
new Framework(
"AppGuardCore",
Path.Combine(LibPath, "AppGuardCore.framework.zip"),
"",
true //<- Add: Set to Embed&Sign
)
);
string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory,
Target.RelativeEnginePath);
AdditionalPropertiesForReceipt.Add("IOSPlugin",
Path.Combine(PluginPath, "AppGuardSDK_UPL_IOS.xml"));
}
Note that AppGuard for iOS SDK version v1.10.2.0 or later only uses NSPrivacyAccessedAPICategoryUserDefaults from the required reason API items in Apple's Privacy Manifest.
Once you complete the steps above, the AppGuard SDK integration is finished.