Link Search Menu Expand Document

Unity - Integrating the Snapyr SDK for iOS

This page explains how to configure your project with the Snapyr SDK for push notifications and adds details on completing an Xcode build successfully, after exporting your project from Unity to Xcode.

For more details on getting started with Unity, see the main Unity SDK documentation page.

Adding push notification handling support

In order to display incoming push notifications, track receipt of and user interaction with notifications against your Snapyr campaigns, and handle deep link opens, we’ll need to make some code updates.

In particular, we’ll need to make changes to the AppDelegate. In the case of a Unity build, this is part of the UnityAppController.

  1. First, open UnityAppController.h and add the following to the top of the file:

     //  System Versioning Preprocessor Macros
     #define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
     #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
    
     // Add references to the UserNotification framework, which is used to interact with the notification system...
     #import <UserNotifications/UNUserNotificationCenter.h>
     #import <UserNotifications/UserNotifications.h>
     // ... as well as the Snapyr SDK:
     #import <Snapyr/Snapyr.h>
    
  2. Then, find the following line:

     @interface UnityAppController : NSObject<UIApplicationDelegate>
    
  3. … and replace with the following, to have the UnityAppController implement the UNUserNotificationCenterDelegate interface:

     @interface UnityAppController : NSObject<UIApplicationDelegate, UNUserNotificationCenterDelegate>
    
  4. Now open UnityAppController.mm, where we’ll implement the main code for handling notifications.

  5. Find the method didFinishLaunchingWithOptions.

    You’ll need your app’s Snapyr Write Key. To obtain your write key, please contact Snapyr Customer Service.

    Before the return statement (return YES;), insert the following code, being sure to replace YOUR_WRITE_KEY with your key. You can also set the various configuration options however you wish.

     SnapyrSDKConfiguration *configuration = [SnapyrSDKConfiguration configurationWithWriteKey:@"YOUR_WRITE_KEY"];
     configuration.trackApplicationLifecycleEvents = YES; // Enable this to record certain application events automatically
     configuration.recordScreenViews = YES; // Enable this to record screen views automatically
    
     [SnapyrSDK setupWithConfiguration:configuration];
        
     if( SYSTEM_VERSION_GREATER_THAN( @"10.0" ) ) {
         UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
         center.delegate = self;
         [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
             if( !error ) {
                 // required to get the app to do anything at all about push notifications
                 dispatch_async(dispatch_get_main_queue(), ^{
                     [[UIApplication sharedApplication] registerForRemoteNotifications];
                 });
                 NSLog( @"Push registration success." );
             } else {
                 // The authorization request may fail for various reasons (user denied permission, notifications not supported in simulator, etc.)
                 // In development, these log outputs may help you determine why, but you can remove them if you like.
                 NSLog( @"Push registration FAILED" );
                 NSLog( @"ERROR: %@ - %@", error.localizedFailureReason, error.localizedDescription );
                 NSLog( @"SUGGESTIONS: %@ - %@", error.localizedRecoveryOptions, error.localizedRecoverySuggestion );
             }
         }];
     }
    
  6. After the didFinishLaunchingWithOptions method, add the following code. This will interact with various parts of the push notification handling system. Feel free to customize this code to your needs - for example, you may wish to hide foreground notifications instead of displaying them, so that notifications don’t interrupt your user’s gameplay.

     - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
     {
         // After successful push registration, this code decodes the device token and registers it with Snapyr. This is required to allow Snapyr campaigns to send push notifications to the device.
         NSUInteger dataLength = deviceToken.length;
         if (dataLength == 0) {
             return;
         }
         const unsigned char *dataBuffer = (const unsigned char *)deviceToken.bytes;
         NSMutableString *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];
         for (int i = 0; i < dataLength; ++i) {
             [hexString appendFormat:@"%02x", dataBuffer[i]];
         }
         [[SnapyrSDK sharedSDK] setPushNotificationToken:hexString];
     }
    
     - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
         // This tells Snapyr that a notification successfully arrived on the device, and is required to allow your Snapyr campaigns to track the "received" rate for campaigns.
         [[SnapyrSDK sharedSDK] pushNotificationReceived:userInfo];
         completionHandler(UIBackgroundFetchResultNewData);
     }
    
     - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
     {
         // This tells Snapyr that a notification was tapped, and is required to allow your Snapyr campaigns to track the "clicked" rate for campaigns.
         [[SnapyrSDK sharedSDK] pushNotificationTapped:[response.notification.request.content.userInfo copy]];
            
         // If the notification from the Snapyr campaign has a deep link URL set, the following code will open it.
         NSURL *url = [NSURL URLWithString:response.notification.request.content.userInfo[@"deepLinkUrl"]];
         if (url != nil) {
             UIApplication *application = [UIApplication sharedApplication];
             [application openURL:url options:@{} completionHandler:nil];
         }
         // Do not remove the following line!
         completionHandler();
     }
    
     // Process notification when app is in foreground
     - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
     {
         // This method is triggered if a notification is received while the app is in the foreground. 
         // This tells Snapyr that a notification successfully arrived on the device, and is required to allow your Snapyr campaigns to track the "received" rate for campaigns.
         [[SnapyrSDK sharedSDK] pushNotificationReceived:[notification.request.content.userInfo copy]];
         // Optional: by default, notifications received in the foreground are not displayed. If you would like to display the notification over the app, run the following line.
         completionHandler(UNNotificationPresentationOptionAlert);
         // Alternatively, you can call the completion handler with the following parameter, to not display the notification.
         // completionHandler(UNNotificationPresentationOptionNone);
     }
    

Features to enable rich push notification functionality

Snapyr allows marketers to create push notification templates that include rich media and interaction capabilities, such as embedded images in the notification.

In order to enable these capabilities, we need to add a Notification Service Extension to the app.

First, add a new Notification Service Extension target to the project:

  1. Open the project settings. Under the target list, click the + on the bottom to add a new target: Add Target

  2. Find and select Notification Service Extension, and click Next. Notification Service Extension

  3. Enter a name of your choice for the extension, and be sure to select your team in the dropdown. Xcode will automatically append the name you enter to the name of the primary target to produce a matching Bundle Identifier. Click Finish to create the extension. Enter Extension Name

    • NOTE: if Xcode shows a prompt asking if you want to activate the new scheme, you can simply click Cancel.

You now have a Notification Service Extension! Now we need to update the code in NotificationService.swift to handle rich push features.

In the Xcode file navigator, find and open NotificationService.swift under the new extension, and update the code to the following:

import UserNotifications

class NotificationService: UNNotificationServiceExtension {

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

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        // This method will be called when the notification arrives on the device, before the notification is displayed
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            // Download Snapyr-provided image from URL, if specified
            if let snapyrData = request.content.userInfo["snapyr"] as? Dictionary<String, AnyObject>,
               let urlPath = snapyrData["imageUrl"] as? String,
               let url = URL(string: urlPath) {
                // Notification image must be a url to a local (on-disk) file...
                // Fetch image from network and store in a temp file
                let destination = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(url.lastPathComponent)
                do {
                    let data = try Data(contentsOf: url)
                    try data.write(to: destination)
                    // empty string identifier lets system generate its own unique ID
                    let attachment = try UNNotificationAttachment(identifier: "", url: destination)
                    bestAttemptContent.attachments = [attachment]
                } catch {
                    // On failure, do nothing - notification will continue to process w/o image
                    print("Could not fetch notification image from URL")
                }
            }
            
            contentHandler(bestAttemptContent)
        }
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // In the event that processing rich features takes longer than iOS allows, we'll continue to display the basic notification.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }

}