Overview

Skill Level: Intermediate

This tutorial provides information for iOS action plug-in for enhanced notifications, as well as an action plug-in architectural overview.

Prerequisites

Not what you’re looking for? Check out all our available tutorials for mobile app messaging here.

 

 

Step-by-step

  1. Action plug-ins for enhanced notifications

    There are four action plug-ins you can use to enhance your mobile app message:

    • Add to Calendar
    • Snooze
    • Add to Passbook
    • Web Action
    • iOS image Carousel (For details, see here.)

    You can use any of the plug-ins by adding the set of files for the plug-in and registering it. Each plug-in requires certain parameters.

    • Add to Calendar plug-in 

    The Add to Calendar plug-in allows a user to add an event to the calendar. This action happens in the background without opening the calendar.

    {
    "interactive": true/false,// true = brings up interface to add event
    "title": "<event title>", // text
    "timeZone": "<timezone>", // text (optional)
    "startDate": "<the event start datetime>", // formatted like 2015-04-07T10:10:10Z
    "endDate": "<the event and datetime>", // formatted like 2015-04-07T10:10:10Z
    "description": "<event notes>", // text (saved to notes)
    "type": "calendar" // constant
    }
    

    If the time or timezone fields are incorrect, the timezone of the device is used. You can show the calendar user interface for adding an item to the calendar by adding interactive = true or false in the payload. If false, it does it in the background. Calendar requires AddToCalendarPlugin.h and AddToCalendarPlugin.m.
    Note: For iOS 10 applications, add a description to NSCalendarsUsageDescription in the info.plist file that provides a reason to the user for allowing the app to add the calendar event.

    • Snooze plug-in 

    The Snooze plug-in allows a user to bring back the mobile app message after some time.

    {
    	"value": "<minutes to wait>",
    	"type": "snooze"        // Constant
    }
    
    • Add to Passbook plug-in 

    The Add to Passbook plug-in allows a user to add a pass to Passbook with a single click.

    {
    "value": "<url>" // url of server that can vend the pass (https only)
    "type": "passbook" // Constant
    }
    
    • Web Action plug-in 

    The Web Action plug-in allows a mobile app user to view a web page inside the app.

    {
    "value": "<url>",// Url of web page to show (https only)
    "type": "displayWebView"// Constant
    }
    

    Web Action requires the following files in the plugins/web-action folder: WebActionPlugin.h, WebActionPlugin.m, WebViewController.h, and WebViewController.m. Then, register it in the AppDelegate.

    The following example shows how to implement the plug-ins in your AppDelegate init method for iOS:

    -(instancetype)init
    {
    if(self = [super init])
    {
    [SnoozeActionPlugin registerPlugin];
    }
    return self;
    }
    

    You can also implement all four plug-ins:

    -(instancetype)init
    {
    if(self = [super init])
    {
    [SnoozeActionPlugin registerPlugin];
    [AddToCalendarPlugin registerPlugin];
    [AddToPassbookPlugin registerPlugin];
    [WebActionPlugin registerPlugin];
    }
    return self;
    }
    

    Write your own plug-in

    If you want to write your own plug-in, you can adapt the Example plug-in that ships with the SDK. For more information, see Creating custom actions for mobile app messages.

  2. Action plug-in architecture overview

    When an action is triggered, the system looks for handlers that match the types registered. You can use two types of action plug-in approaches: simple or advanced.

    The simple method consists of modifying the main.m file to point to MCEAppDelegate and setting the AppDelegate class in the configuration file to your AppDelegate class name. When you use this method of integration, the MCEAppDelegate class runs all the required methods at their required integration points and passes over control to all calls back to your AppDelegate class. This works for any custom methods that you want to use because it proxys the callback to the AppDelegate class.

    The plug-ins in the sample app are used by following this process. For the simple approach, drag all source files into the project. In the AppDelegate class, add the plug-in initialization code:

    -(instancetype)init
    {
        if(self = [super init])
        {
            [WebActionPlugin registerPlugin]; // if web action plugin is being used
            [ActionMenuPlugin registerPlugin]; // if action menu plugin is being used
        }
        return self;
    }
    

    You can register any action handlers that you want by implementing the following code.

    In the AppDelegate class, add the plug-in initialization code.

    -(instancetype)init
    
    {
    
    if(self = [super init])
    
    {
    
    MCEActionRegistry * registry = [MCEActionRegistry sharedInstance];
    
    [registry registerTarget: self withSelector:@selector(custom:) forAction: @"custom"];
    
    }
    
    return self;
    
    }
    

    Implement the custom action:

    -(void)showActionsMenu:(NSDictionary*)action
    {
        // Do something with action here
    }
    

    You can use an alternative method that includes both the action payload and the rest of the APNs payload:

    • In the AppDelegate class, add the plugin initialization code.

    -(instancetype)init
    
    {
    
    if(self = [super init])
    
    {
    
    MCEActionRegistry * registry = [MCEActionRegistry sharedInstance];
    
    [registry registerTarget: self withSelector:@selector(custom:payload:) forAction: @"custom"];
    
    }
    
    return self;
    
    }
    

    Implement the custom action:

    -(void)showActionsMenu:(NSDictionary*)action payload:(NSDictionary*)payload
    {
        // Do something with action and payload here
    }
    

    You can create a class that registers with the MCEActionRegistry system as shown in the following example for the WebActionPlugin.h file. The following example overrides the default handling of the url type with a web view inside the application instead of the default handling of opening Safari.

    #import <Foundation/Foundation.h> 
    #import <MobileEngagement/MobileEngagement.h>
    
    
    @interface WebActionPlugin : NSObject
    -(void)performAction:(NSDictionary*)action;
    +(void)registerPlugin;
    @end
    

    The following example shows the WebActionPlugin.m file.

    #import "WebActionPlugin.h"
    #import "WebViewController.h"
    
    @implementation WebActionPlugin
    
    -(void)performAction:(NSDictionary*)action
    {
        WebViewController * viewController = [[WebViewController alloc] initWithURL:[NSURL URLWithString:action[@"value"]]];
        UIWindow * window = [[UIApplication sharedApplication] keyWindow];
        [window.rootViewController presentViewController:viewController animated:TRUE completion:nil];
    }
    
    +(void)registerPlugin
    {
        MCEActionRegistry * registry = [MCEActionRegistry sharedInstance];
    
        [registry registerTarget: [self sharedInstance] withSelector:@selector(performAction:) forAction: @"url"];
    }
    + (instancetype)sharedInstance
    {
        static id sharedInstance = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedInstance = [[self alloc] init];
        });
        return sharedInstance;
    }
    @end
    

    Register the class in your AppDelegate at launch time, as shown in the following code:

    -(instancetype)init
    {
        if(self = [super init])
        {
            [WebActionPlugin registerPlugin];
        }
        return self;
    }
    

    The advanced method involves implementing certain methods on your AppDelegate class instead of using the previous instructions. You must implement the following methods:

    -(void)applicationDidFinishLaunching:(UIApplication *)application
    {
        [[MCESdk sharedInstance] handleApplicationLaunch];
        if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
        {
            UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil];
            [application registerUserNotificationSettings:settings];
            [application registerForRemoteNotifications];
        }
    }
    
    -(void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
        [[MCESdk sharedInstance]registerDeviceToken:deviceToken];
    }
    
    - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler
    {
        [[MCESdk sharedInstance] processCategoryNotification: userInfo identifier:identifier fetchCompletionHandler:completionHandler];
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    {
        [[MCESdk sharedInstance] presentOrPerformNotification: userInfo];
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    {
        [[MCESdk sharedInstance] presentDynamicCategoryNotification: userInfo fetchCompletionHandler:completionHandler];
    }
    
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
    {
        [[MCESdk sharedInstance] presentOrPerformNotification: notification.userInfo];
    }
    
    - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler
    {
        [[MCESdk sharedInstance] processDynamicCategoryNotification: notification.userInfo identifier:identifier fetchCompletionHandler:completionHandler];
    }
    

Expected outcome

Need more help? Check out all of our available tutorials for mobile app messaging here.

 

Join The Discussion

Your email address will not be published. Required fields are marked *