Unreal Engine SDK - Uninstall Tracking

Uninstall Tracking

Track app uninstalls to measure user retention and optimize re-engagement campaigns by integrating push notification services with the Singular SDK.

Important: Google deprecated GCM APIs in April 2018. Use Firebase Cloud Messaging (FCM) for all Android uninstall tracking implementations.

Android Uninstall Tracking

Prerequisites

Before implementing uninstall tracking in your Unreal Engine app, configure your app in the Singular platform following the guide Setting Up Android Uninstall Tracking.


System Requirements

Uninstall tracking requires Firebase Cloud Messaging and specific device configurations.

FCM Requirements (source):

  • Android Version: Devices must run Android 4.1 (API 16) or higher
  • Google Play Services: Devices must have the Google Play Store app installed
  • Emulator Support: Android 4.1+ emulators with Google APIs are supported
  • Distribution: Apps can be distributed outside the Google Play Store while still supporting uninstall tracking

Note: Users on unsupported Android versions or devices without Google Play Services will not be tracked for uninstalls.


Implementation Steps

Step 1: Integrate Firebase Cloud Messaging

Set up Firebase Cloud Messaging in your Unreal Engine app if not already configured.

Follow Google's official guide to Set up a Firebase Cloud Messaging client app on Android. This includes:

  1. Add Firebase to your Android project
  2. Add the Firebase Messaging dependency to your build.gradle file
  3. Configure Firebase settings in google-services.json
  4. Request notification permissions (Android 13+)

Step 2: Configure AndroidManifest.xml

Register your Firebase Messaging Service in the Android manifest to receive FCM messages.

AndroidManifest.xml
<service 
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

Important: Replace .java.MyFirebaseMessagingService with the fully qualified name of your class that extends FirebaseMessagingService.


Step 3: Register FCM Device Token

Retrieve the FCM device token and send it to Singular for uninstall tracking using the SetUninstallToken method.

C++
// After initializing Singular SDK, register the FCM token
void AYourGameMode::RegisterFCMToken()
{
    // Get FCM token from Firebase Messaging
    // This assumes you have Firebase integrated and can retrieve the token
    FString FCMToken = GetFirebaseCloudMessagingToken();

    if (!FCMToken.IsEmpty())
    {
        // Register token with Singular
        USingularSDKBPLibrary::SetUninstallToken(FCMToken);
        UE_LOG(LogTemp, Log, TEXT("FCM token registered with Singular: %s"), *FCMToken);
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("FCM token is empty"));
    }
}

// Example helper method to get FCM token (platform-specific implementation required)
FString AYourGameMode::GetFirebaseCloudMessagingToken()
{
    FString Token;

    #if PLATFORM_ANDROID
    // Use JNI to call Firebase Messaging getToken() method
    // This requires platform-specific code to access Firebase SDK
    if (JNIEnv* Env = FAndroidApplication::GetJavaEnv())
    {
        // Implement JNI call to Firebase Messaging getToken()
        // Example: Token = CallFirebaseGetToken(Env);
        UE_LOG(LogTemp, Log, TEXT("Retrieving FCM token via JNI"));
    }
    #endif

    return Token;
}

Method Signature:

static void SetUninstallToken(FString token);

Parameters:

  • token: The FCM device token as a string

Note: The SetUninstallToken method should be called after the Singular SDK is initialized. The FCM token can be registered at any time after SDK initialization.


Step 4: Handle Token Refresh

Update the FCM token with Singular whenever it refreshes to maintain accurate uninstall tracking.

C++
// Handle FCM token refresh
void AYourGameMode::OnFCMTokenRefresh(const FString& NewToken)
{
    UE_LOG(LogTemp, Log, TEXT("FCM token refreshed: %s"), *NewToken);

    // Update token with Singular
    USingularSDKBPLibrary::SetUninstallToken(NewToken);

    // Also send token to your server if needed
    SendTokenToServer(NewToken);
}

void AYourGameMode::SendTokenToServer(const FString& Token)
{
    // Implement your server communication logic here
    UE_LOG(LogTemp, Log, TEXT("Sending token to server: %s"), *Token);
}

Best Practice: FCM tokens can refresh at any time (app updates, device restore, etc.). Always handle token refresh events to keep Singular updated with the latest token.


iOS Uninstall Tracking

Prerequisites

Uninstall tracking on iOS is based on Apple Push Notification service (APNs) technology.

If your app doesn't support push notifications, see Apple's guide to Registering Your App with APNs.


Registering APNs Device Token

Pass the device token returned from APNs using the SetUninstallToken method after the SDK is initialized.

Method Signature:

static void SetUninstallToken(FString token);

Parameters:

  • token: The device token returned from APNs as a hexadecimal string

Token Format: The APNs token is usually binary data in its native form, but you must pass it to Singular as a hexadecimal string representation.


Usage Example

Register the APNs device token with Singular for iOS uninstall tracking.

C++
// Register APNs token with Singular
void AYourGameMode::RegisterAPNsToken()
{
    #if PLATFORM_IOS
    // Get APNs device token (platform-specific implementation required)
    FString APNsToken = GetAPNsDeviceToken();

    if (!APNsToken.IsEmpty())
    {
        // Pass the token as a hex-string to Singular
        USingularSDKBPLibrary::SetUninstallToken(APNsToken);
        UE_LOG(LogTemp, Log, TEXT("APNs token registered: %s"), *APNsToken);
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("Failed to get APNs device token"));
    }
    #endif
}

// Example helper method to get APNs token (platform-specific implementation required)
FString AYourGameMode::GetAPNsDeviceToken()
{
    FString Token;

    #if PLATFORM_IOS
    // Use Objective-C++ to access APNs token
    // This requires platform-specific code in a .mm file
    // Example: Token = GetIOSDeviceToken();
    UE_LOG(LogTemp, Log, TEXT("Retrieving APNs token"));
    #endif

    return Token;
}

Example Token:

// Pass the APNs token as a hex-string
USingularSDKBPLibrary::SetUninstallToken(TEXT("ba85ab31a7c7f5c2f012587f29fb0e596d4b67e7b7b2838fa1a8582c1f7dbdee"));

Platform Consistency: The SetUninstallToken method works identically for both Android (FCM) and iOS (APNs). Call it after SDK initialization on both platforms.


Platform-Specific Token Retrieval

Android FCM Token via JNI

Access Firebase Cloud Messaging token using JNI (Java Native Interface) in Unreal Engine.

C++
#if PLATFORM_ANDROID
#include "Android/AndroidJNI.h"
#include "Android/AndroidApplication.h"

FString AYourGameMode::GetFirebaseCloudMessagingToken()
{
    FString Token;

    if (JNIEnv* Env = FAndroidApplication::GetJavaEnv())
    {
        // Get FirebaseMessaging class
        jclass FirebaseMessagingClass = FAndroidApplication::FindJavaClass(
            "com/google/firebase/messaging/FirebaseMessaging"
        );

        if (FirebaseMessagingClass != nullptr)
        {
            // Get getInstance() method
            jmethodID GetInstanceMethod = Env->GetStaticMethodID(
                FirebaseMessagingClass,
                "getInstance",
                "()Lcom/google/firebase/messaging/FirebaseMessaging;"
            );

            // Call getInstance()
            jobject FirebaseMessagingInstance = Env->CallStaticObjectMethod(
                FirebaseMessagingClass,
                GetInstanceMethod
            );

            if (FirebaseMessagingInstance != nullptr)
            {
                // Get getToken() method
                jmethodID GetTokenMethod = Env->GetMethodID(
                    FirebaseMessagingClass,
                    "getToken",
                    "()Lcom/google/android/gms/tasks/Task;"
                );

                // Note: getToken() returns a Task, so you need to implement
                // async handling or use addOnCompleteListener
                // This is a simplified example - production code requires
                // proper Task handling

                UE_LOG(LogTemp, Log, TEXT("FCM token retrieval initiated"));
            }

            Env->DeleteLocalRef(FirebaseMessagingClass);
        }
    }

    return Token;
}
#endif

Implementation Note: Firebase's getToken() returns a Task object that resolves asynchronously. Production implementations should use Firebase's Task API with completion listeners to properly retrieve the token.


iOS APNs Token via Objective-C++

Access Apple Push Notification service token using Objective-C++ in Unreal Engine.

Implementation Approach: Create a separate .mm (Objective-C++) file in your Unreal Engine project to interface with iOS APNs APIs. Expose C++ callable functions that retrieve the device token and convert it to a hexadecimal string.

Example Objective-C++ Implementation (YourProject_IOS.mm):

Objective-C++
// YourProject_IOS.mm
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>

// Convert NSData to hex string
NSString* ConvertTokenToHexString(NSData* deviceToken)
{
    const unsigned char* bytes = (const unsigned char*)[deviceToken bytes];
    NSMutableString* hexString = [NSMutableString string];

    for (NSUInteger i = 0; i < [deviceToken length]; i++)
    {
        [hexString appendFormat:@"%02x", bytes[i]];
    }

    return hexString;
}

// C++ callable function to get APNs token
extern "C" const char* GetIOSAPNsToken()
{
    UIApplication* app = [UIApplication sharedApplication];

    // Request notification authorization
    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | 
                                             UNAuthorizationOptionSound | 
                                             UNAuthorizationOptionBadge)
                          completionHandler:^(BOOL granted, NSError* error)
    {
        if (granted)
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                [app registerForRemoteNotifications];
            });
        }
    }];

    // Note: The actual token is received in application:didRegisterForRemoteNotificationsWithDeviceToken:
    // You need to implement an AppDelegate to capture this

    return nullptr; // Token is received asynchronously
}

Async Implementation: APNs token registration is asynchronous. Implement proper AppDelegate methods to capture the token when it's received and then call SetUninstallToken.


Verification and Troubleshooting

Verify Implementation

Confirm uninstall tracking is working correctly.

  1. Check Logs: Verify token registration appears in your Unreal Engine output logs
  2. Test Token Generation: Ensure tokens are generated on first app launch
  3. Monitor Dashboard: Check Singular dashboard for uninstall tracking data after 24-48 hours
  4. Test Token Refresh: Clear app data and verify token updates correctly

Common Issues

  • Android Token Not Generated: Verify Firebase dependencies are correctly added and google-services.json is configured in your Unreal Engine Android project
  • Token Not Updating: Implement proper token refresh handling for both FCM and APNs
  • Missing Data: Ensure devices meet platform requirements (Android 4.1+ with Google Play Services, iOS with APNs support)
  • Configuration Error: Confirm uninstall tracking is enabled in Singular platform settings
  • JNI Errors: Verify Firebase classes are properly included in your Android build and ProGuard rules don't strip necessary classes
  • iOS Token Format: Ensure APNs token is properly converted from binary data to hexadecimal string format

Additional Resources: For detailed troubleshooting, see the Android Uninstall Tracking Setup Guide and Firebase Cloud Messaging for Android Documentation.


Method Reference

SetUninstallToken

Register push notification tokens (FCM for Android, APNs for iOS) with Singular to enable uninstall tracking.

Property Details
Description Pass the device token returned from APNs (iOS) or FCM (Android). The token is usually binary data in the native form, but you need to pass it as a string.
Signature static void SetUninstallToken(FString token)
Parameters token: FCM or APNs device token as a string (hex format for APNs)
Platform Android (FCM), iOS (APNs)
Timing Call after SDK initialization

Usage Examples:

C++
// Android FCM token
FString FCMToken = TEXT("eXaMpLeToKeN123456789abcdef");
USingularSDKBPLibrary::SetUninstallToken(FCMToken);

// iOS APNs token (hex-string format)
FString APNsToken = TEXT("ba85ab31a7c7f5c2f012587f29fb0e596d4b67e7b7b2838fa1a8582c1f7dbdee");
USingularSDKBPLibrary::SetUninstallToken(APNsToken);