Push

Prev Next

Available in Classic and VPC

It enables developers to efficiently send messages from servers or the cloud to mobile devices. Using Push allows you to send notification messages to mobile apps and web apps. Push supports various platforms, including iOS and Android applications.

Dashboard settings

To use the Push service, you must first prepare the keys for each platform and then configure them in the dashboard.

How to create FCM push key

To issue a FCM push key, follow these steps in order.

  1. Click Firebase console > Project settings > Cloud messaging > Manage service accounts.
    ko-gamepot3-push01.png

  2. Select Google Cloud > Service accounts > Created email account.
    ko-gamepot3-push02.png

  3. Select Keys > Add key > Create new key > Key type as "JSON," and then click the [Create] button.

    • If you have a previously created key, you can use that file.
      ko-gamepot3-push03.png

How to create APNs authentication key

The APNs authentication key is essential for sending iOS push notifications, so make sure to obtain it by following the steps below.

  1. Log in to Apple Developer site > Certificates, IDs & Profiles > Select Keys > Click the [+] button to create a new key.

    • You can only create up to 2 push authentication keys.
      ko-gamepot3-push04.png
  2. Enter the key name, and then activate the Apple Push Notification service (APNs).
    ko-gamepot3-push05.png

  3. Click the [Register] button to get your authentication key.
    ko-gamepot3-push06.png

  4. Check the key ID and download it.

    • The downloaded file has the extension .p8.
    • Key files can only be downloaded once.
      ko-gamepot3-push07.png

How to set dashboard key

The issued key must be registered in the GAMEPOT dashboard to send push notifications properly.

  • Project settings - Integration - Google Android (FCM) Configuration

    • Sender ID: Firebase console > Project settings > Cloud messaging > Sender ID
    • Private Key (JSON file): Open the JSON file created in the FCM push key creation method with a program such as Notepad or a text editor, copy the entire content, and register it.
  • Project settings - Integration - Apple iOS (APNs) Configuration

    • Certificate: Open the .p8 file created in the APNs authentication key creation method with a program such as Notepad or a text editor, copy the entire content, and register it.
    • Key ID: Register the key ID of the .p8 file created in APNs authentication key creation method.
    • Team ID: Enter the team ID from the Apple Developer site "Membership Details."
    • Bundle ID: Enter the Bundle Identifier value of the app package.

How to set up push

You must complete the SDK setup for each platform to receive push notifications properly.

AOS Native

When using the GAMEPOT Android SDK, integrate push by following the steps below.

Integrate Firebase Messaging

To receive Android push notifications, you need to integrate FCM (Firebase Cloud Messaging). Follow the steps below to integrate FCM.

  1. Create Firebase project and register app

    • Create a new project in the Firebase console.
    • Add the Android app to the project and enter the package name.
    • Download the google-services.json file and add it to the root directory of the app module.
  2. build.gradle settings

    • Add the following plugins and dependencies to the build.gradle.kts file of the app module.
    • Kotlin:
    plugins {
         id("com.google.gms.google-services")
    }
    dependencies {
         implementation("com.google.firebase:firebase-messaging-ktx:23.2.1")
    }
    
    • Add the following plugins to the build.gradle.kts file of the project root.
    • Kotlin:
    plugins {
         id("com.google.gms.google-services") version "4.4.1" apply false
    }
    
  3. Reset FCM and manage token

    • When the app launches, FCM automatically resets and a device token is issued.
    • Register the token on the server to use it for sending push messages.
  4. Troubleshooting

    • If you encounter the Default FirebaseApp is not initialized error, double-check your Gradle settings.
    • If the google-services.json file is missing, download it again from the Firebase console and place it in the correct location.

Set push notification icon

You can set small icons to display in the notification bar when receiving push messages. If you don't set it up separately, then the default image included in the SDK is used. You can set up icons that suit the game.

If you create it using Android Asset Studio, it is convenient as the images are generated for each folder automatically.

The following describes how to set push notification icons.

  1. Create res/drawable folders respectively in the following path, and then add image files for each size.
    • The following table provides guidance on folder sizes and recommended icon sizes by resolution.
Folder name Capacity
res/drawable-mdpi/ 24x24
res/drawable-hdpi/ 36x36
res/drawable-xhdpi/ 48x48
res/drawable-xxhdpi/ 72x72
res/drawable-xxxhdpi/ 96x96
  1. Change the name of the image files to ic_stat_nbase_small.

iOS Native

When using the GAMEPOT iOS SDK, integrate push by following the steps below.

Reset push feature

To enable the Push feature, configure the notification permission request and token registration logic through AppDelegate.

The AppDelegate configuration examples for Swift and Objective-C are as follows:

  • Swift:
import NBase

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    registerForRemoteNotifications()
    return true
}

func registerForRemoteNotifications() {
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, _ in
        if granted {
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        } else {
            print("The push notification permission has been denied")
        }
    }
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    NBase.setPushToken(token: token)
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    NBase.setPushToken(token: "")
}
  • Objective-C:
#import "[ProjectName]-Swift.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    center.delegate = self;

    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge)
                         completionHandler:^(BOOL granted, NSError * _Nullable error) {
        if (granted) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [[UIApplication sharedApplication] registerForRemoteNotifications];
            });
        } else {
            NSLog(@"Push permission denied");
        }
    }];

    return YES;
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSString *token = [self stringWithDeviceToken:deviceToken];
    [NBaseBridge.shared setPushToken:token];
}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Failed to register for remote notifications: %@", error);
}

- (void)userNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification
         withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
            
    completionHandler(UNNotificationPresentationOptionBanner | 
                     UNNotificationPresentationOptionSound | 
                     UNNotificationPresentationOptionBadge);
}

- (NSString *)stringWithDeviceToken:(NSData *)deviceToken {
    NSUInteger length = deviceToken.length;
    if (length == 0) {
        return nil;
    }
    const unsigned char *buffer = deviceToken.bytes;
    NSMutableString *hexString = [NSMutableString stringWithCapacity:(length * 2)];
    for (int i = 0; i < length; ++i) {
        [hexString appendFormat:@"%02x", buffer[i]];
    }
    return [hexString copy];
}

Image push

You need to add a notification service extension to receive and process notification images in the iOS app.

  • Swift:
  1. Add Notification Service Extension to TARGETS in the Xcode project.
  2. Edit the NotificationService.swift file of the created Notification Service Extension module as follows:
import UserNotifications

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        guard let bestAttemptContent = bestAttemptContent,
              let userInfo = request.content.userInfo as? [String: Any] else {
            contentHandler(request.content)
            return
        }

        let imageURL = userInfo["imageUrl"] as? String ??
                      userInfo["gcm.notification.image"] as? String

        guard let imageURL = imageURL, !imageURL.isEmpty else {
            contentHandler(bestAttemptContent)
            return
        }

        downloadAndAttachImage(urlString: imageURL) { attachment in
            if let attachment = attachment {
                bestAttemptContent.attachments = [attachment]
            }
            DispatchQueue.main.async {
                contentHandler(bestAttemptContent)
            }
        }
    }

    private func downloadAndAttachImage(urlString: String, completionHandler: @escaping (UNNotificationAttachment?) -> Void) {
        guard let url = URL(string: urlString.trimmingCharacters(in: .whitespaces)) else {
            completionHandler(nil)
            return
        }

        let session = URLSession(configuration: .ephemeral)
        let task = session.downloadTask(with: url) { (location, response, error) in
            if let error = error {
                completionHandler(nil)
                return
            }
            
            guard let location = location else {
                completionHandler(nil)
                return
            }

            let fileManager = FileManager.default
            let tmpDirectory = NSTemporaryDirectory()
            let tmpFile = "image_\(Date().timeIntervalSince1970).png"
            let tmpPath = (tmpDirectory as NSString).appendingPathComponent(tmpFile)
            let tmpURL = URL(fileURLWithPath: tmpPath)

            do {
                if fileManager.fileExists(atPath: tmpPath) {
                    try fileManager.removeItem(atPath: tmpPath)
                }
                try fileManager.moveItem(at: location, to: tmpURL)

                let attachment = try UNNotificationAttachment(
                    identifier: UUID().uuidString,
                    url: tmpURL,
                    options: [UNNotificationAttachmentOptionsTypeHintKey: "public.png"]
                )
                completionHandler(attachment)
            } catch {
                completionHandler(nil)
            }
        }

        task.resume()

        DispatchQueue.main.asyncAfter(deadline: .now() + 25) {
            task.cancel()
        }
    }

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}
  • Objective-C:
  1. Add Notification Service Extension to TARGETS in the Xcode project.
  2. Edit the NotificationService.m file of the created Notification Service Extension module as follows:
#import "NotificationService.h"

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];

    NSDictionary *userInfo = request.content.userInfo;
    NSString *imageUrl = userInfo[@"imageUrl"];
    if (!imageUrl) {
        imageUrl = userInfo[@"gcm.notification.image"];
    }

    if (imageUrl && imageUrl.length > 0) {
        [self downloadAndAttachImage:imageUrl completionHandler:^(UNNotificationAttachment *attachment) {
            if (attachment) {
                self.bestAttemptContent.attachments = @[attachment];
            }
            self.contentHandler(self.bestAttemptContent);
        }];
    } else {
        self.contentHandler(self.bestAttemptContent);
    }
}

- (void)downloadAndAttachImage:(NSString *)urlString completionHandler:(void(^)(UNNotificationAttachment *attachment))completionHandler {
    NSURL *url = [NSURL URLWithString:[urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
    if (!url) {
        completionHandler(nil);
        return;
    }

    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
    [[session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
        if (error) {
            completionHandler(nil);
            return;
        }
        
        if (!location) {
            completionHandler(nil);
            return;
        }

        NSString *tmpDirectory = NSTemporaryDirectory();
        NSString *tmpFile = [NSString stringWithFormat:@"image_%f.png", [[NSDate date] timeIntervalSince1970]];
        NSString *tmpPath = [tmpDirectory stringByAppendingPathComponent:tmpFile];
        NSURL *tmpURL = [NSURL fileURLWithPath:tmpPath];

        NSFileManager *fileManager = [NSFileManager defaultManager];
        if ([fileManager fileExistsAtPath:tmpPath]) {
            [fileManager removeItemAtPath:tmpPath error:nil];
        }

        NSError *moveError = nil;
        [fileManager moveItemAtURL:location toURL:tmpURL error:&moveError];
        if (moveError) {
            completionHandler(nil);
            return;
        }

        NSError *attachmentError = nil;
        UNNotificationAttachment *attachment = [UNNotificationAttachment attachmentWithIdentifier:[[NSUUID UUID] UUIDString]
                                                                                              URL:tmpURL
                                                                                          options:@{UNNotificationAttachmentOptionsTypeHintKey: @"public.png"}
                                                                                            error:&attachmentError];

        if (attachmentError) {
            completionHandler(nil);
            return;
        }

        completionHandler(attachment);
    }] resume];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [session invalidateAndCancel];
    });
}

- (void)serviceExtensionTimeWillExpire {
    if (self.contentHandler && self.bestAttemptContent) {
        self.contentHandler(self.bestAttemptContent);
    }
}

Unity

For Unity-based projects, you must configure configuration files and dependencies to support both Android and iOS builds.

Add Firebase configuration file

To use Android push notifications (Firebase Messaging) in Unity, prepare the Firebase configuration file as follows:

  1. Register the Android app in the Firebase console and download the google-services.json file.
  2. Add the downloaded google-services.json file to the ./Assets folder in the Unity project.
    • Path example: ./Assets/google-services.json

Add Unity FCM SDK

To integrate the FCM SDK in Unity, add the library as follows:

  1. Add the firebase-messaging-ktx library to the /Assets/NBaseSDK/Editor/NBaseSDKDependencies.xml path.
  • XML:
<dependencies>
    <androidPackages>
        <androidPackage spec="io.nbase:nbasesdk:3.0.xx"/>
        <androidPackage spec="com.google.firebase:firebase-messaging-ktx:23.2.1" />
    </androidPackages>
    <iosPods>
    </iosPods>
</dependencies>
  1. Click Assets > External Dependency Manager > Android Resolver > Force Resolve to force apply the library dependency.

Set push notification icon (Unity)

You can set a small icon to display in the notification bar when receiving Unity push messages. If not set separately, the default image included in the SDK is used, and you can set the icon that fits your game.

If you create it using Android Asset Studio, it is convenient as the images are generated for each folder automatically.

The following describes how to set the push notification icon in Unity Engine versions 202x and later.

  1. Create res/drawable folders respectively in the following path, and then add image files for each size.
    • The following table describes the resource paths and resolutions.
Folder name Capacity
/Assets/Plugins/Android/GamePotResources.androidlib/res/drawable-mdpi/ 24x24
/Assets/Plugins/Android/GamePotResources.androidlib/res/drawable-hdpi/ 36x36
/Assets/Plugins/Android/GamePotResources.androidlib/res/drawable-xhdpi/ 48x48
/Assets/Plugins/Android/GamePotResources.androidlib/res/drawable-xxhdpi/ 72x72
/Assets/Plugins/Android/GamePotResources.androidlib/res/drawable-xxxhdpi/ 96x96
  1. Add the library to mainTemplate.gradle.
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project('GamePotResources.androidlib') // Add
    ...
}
  1. Change the name of the image files to ic_stat_nbase_small.

Push status

Implement a feature within the app that allows users to directly manage their push notification consent status.

Set push status

To receive push notifications, you must set the push status to true. The meaning of each parameter used to change the push status is as follows:

Parameter description

  • push: Push notification consent status (true/false)
  • night: Night push notification consent status (based on KST, true/false)
  • ad: Ad push notification consent status (true/false). If the ad push value is false, push messages don't come through, regardless of the general/night push settings.
  • token: Push token value

To change the push notification reception settings, call the following code after logging in.

  • Kotlin:
val pushToken = NBase.getPushToken()
val pushState = com.nbase.sdk.model.PushState(
    push = enable,
    night = night,
    ad = ad,
    token = pushToken
)
NBase.setPushState(pushState) { status, e ->
    if (e != null) {
        // failed.
    } else {
        // succeeded.
    }
}
  • Java:
String pushToken = _NBase.getPushToken();
com.nbase.sdk.model.PushState pushState = new com.nbase.sdk.model.PushState(
    Boolean.parseBoolean(enable),
    Boolean.parseBoolean(night),
    Boolean.parseBoolean(ad),
    pushToken
);
NBase nBase = NBase.INSTANCE;
nBase.setPushState(pushState, (status, e) -> {
    if (e != null) {
        // failed.
    } else {
        // succeeded.
    }
    return null;
});
  • Swift:
NBase.setPushState(enable: enable, ad: ad, night: night, token: NBase.getPushToken()) { result in
    switch result {
    case .success:
        // succeeded.
    case .failure:
        // failed.
    }
}
  • Objective-C:
BOOL enable = YES;
BOOL night = NO;
BOOL ad = YES;
NSString *token = [NBaseBridge.shared getPushToken];

[NBaseBridge.shared setPushState:enable night:night ad:ad token:token :^(NSDictionary * _Nullable result, NSError * _Nullable error) {
    if (error) {
        // failed.
    } else {
        // succeeded.
    }
}];
  • C#:
bool push = true;
bool ad = true;
bool night = false;
string token = ""; // If you enter an empty value, the existing token is retained.

NBaseSDK.NBase.setPushState(push, ad, night, token, (pushState, error) => {
    if (error != null)
    {
        // failed.
    }
    else
    {
        // succeeded.
    }
});

Check push status

To check the user's current push consent status, see the following example.

  • Kotlin:
NBase.getPushState() { state, e ->
    if (e != null) {
        // failed.
    } else {
        // succeeded.
    }
}
  • Java:
NBase nBase = NBase.INSTANCE;
nBase.getPushState((state, e) -> {
    if (e != null) {
        // failed.
    } else {
        // succeeded.
    }
    return null;
});
  • Swift:
NBase.getPushState() { result in
    switch result {
    case .success:
        // succeeded.
    case .failure:
        // failed.
    }
}
  • Objective-C:
[NBaseBridge.shared getPushState:^(NSDictionary * _Nullable result, NSError * _Nullable error) {
    if (error) {
        // failed.
    } else {
        // succeeded.
    }
}];
  • C#:
NBaseSDK.NBase.getPushState((pushState, error) => {
    if (error != null)
    {
        // failed.
    }
    else
    {
        // succeeded.
    }
});

How to test push (mobile)

To check if push notifications are functioning properly in the mobile environment, see the following testing procedure.

  • GAMEPOT dashboard: You can check whether push notifications were sent via Dashboard > Message > Push notifications menu.

  • Android (Firebase console) test: Click the New campaign button in the Firebase console > Select project > Messaging > Campaign to send a test message.
    ko-gamepot-push02.png

    ko-gamepot-push03.png

    After entering the push token collected from the app and clicking the Test button, you can check whether it is sent using that token.

  • iOS (CloudKit console) test: Create a new Notifications in the CloudKit console > Push Notifications menu.
    CloudKit_Push Notifications.png

    Enter the device token and payload, then check the delivery result.

Troubleshooting

Common errors and their solutions are as follows:

Q. java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process {package name}. Make sure to call FirebaseApp.initializeApp(Context) first.

A. This error occurs when push settings are missing in the Gradle file. Check the following:

Check the top-level build.gradle.kts file in the project.

  • Gradle (project root):
plugins {
    id("com.google.gms.google-services") version "4.4.1" apply false
}

Check build.gradle.kts of the app module.

  • Gradle (module app):
plugins {
    id("com.google.gms.google-services")
}

Q. org.gradle.api.GradleException: File google-services.json is missing. The Google Services Plugin cannot function without it.

A. This error occurs when the google-services.json file can't be found. Make sure the file is correctly placed in the app module's root folder. e.g., ./project folder/app/google-services.json