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:
- Add Firebase to your Android project
- Add the Firebase Messaging dependency to your build.gradle file
- Configure Firebase settings in google-services.json
- Request notification permissions (Android 13+)
Step 2: Configure AndroidManifest.xml
Register your Firebase Messaging Service in the Android manifest to receive FCM messages.
<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.
// 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.
// 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.
// 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.
#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):
// 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.
- Check Logs: Verify token registration appears in your Unreal Engine output logs
- Test Token Generation: Ensure tokens are generated on first app launch
- Monitor Dashboard: Check Singular dashboard for uninstall tracking data after 24-48 hours
- 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:
// Android FCM token
FString FCMToken = TEXT("eXaMpLeToKeN123456789abcdef");
USingularSDKBPLibrary::SetUninstallToken(FCMToken);
// iOS APNs token (hex-string format)
FString APNsToken = TEXT("ba85ab31a7c7f5c2f012587f29fb0e596d4b67e7b7b2838fa1a8582c1f7dbdee");
USingularSDKBPLibrary::SetUninstallToken(APNsToken);