Advanced : iOS Custom Notification Actions

iOS 8 introduced the possibility to define custom actions for a notification and allow the user to take action directly from the presented notification. Here is a quick video that demonstrates it.

Obviously you need to use iOS 8 as the base SDK for your app in order to be able to use these new features. However you still can target iOS 7 (or older) devices by setting your iOS Deployment Target appropriately.

Apple documentation

You should give a look at the Apple documentation of the new classes involved in creating custom notification actions which are UIUserNotificationAction, UIUserNotificationCategory and UIUserNotificationSettings.

You may also check the new category property on the UILocalNotification class.

Lastly if you have access to an Apple App Developer Account you can watch the What's New in iOS Notifications video from the WWDC 2014 conference which is very informative.

Integration into your iOS app

Register your actions

The first step to use custom notification actions is to create and register your actions in the iOS device. The following code illustrates how to do it.

    if ([UIMutableUserNotificationAction class]
        && [UIMutableUserNotificationCategory class]
        && [[UIApplication sharedApplication] respondsToSelector:@selector(currentUserNotificationSettings)]
        && [[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)])
    {
        
        UIMutableUserNotificationAction *yesAction = [[UIMutableUserNotificationAction alloc] init];
        yesAction.identifier = @"yes";
        yesAction.title = @"Yes";
        yesAction.activationMode = UIUserNotificationActivationModeForeground;
        yesAction.destructive = NO;
        yesAction.authenticationRequired = YES; // Ignored with UIUserNotificationActivationModeForeground mode (YES is implied)
        
        UIMutableUserNotificationAction *noAction = [[UIMutableUserNotificationAction alloc] init];
        noAction.identifier = @"no";
        noAction.title = @"No";
        noAction.activationMode = UIUserNotificationActivationModeBackground;
        noAction.destructive = NO;
        noAction.authenticationRequired = NO;
        
        UIMutableUserNotificationCategory *yesNoActionsCategory = [[UIMutableUserNotificationCategory alloc] init];
        yesNoActionsCategory.identifier = @"YesNo";
        [yesNoActionsCategory setActions:@[yesAction, noAction] forContext:UIUserNotificationActionContextDefault]; // You may provide up to 4 actions for this context
        [yesNoActionsCategory setActions:@[yesAction, noAction] forContext:UIUserNotificationActionContextMinimal];
        
        UIUserNotificationSettings *currentNotifSettings = [UIApplication sharedApplication].currentUserNotificationSettings;
        
        UIUserNotificationType notifTypes = currentNotifSettings.types;
        if (notifTypes == 0) {
            notifTypes = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
        }
        
        UIUserNotificationSettings *newNotifSettings = [UIUserNotificationSettings settingsForTypes:notifTypes categories:[NSSet setWithObject:yesNoActionsCategory]];
        [[UIApplication sharedApplication] registerUserNotificationSettings:newNotifSettings];
    }

Explanations:

  • You first start by checking that the system supports the required APIs (in case your app is running on a prior iOS 8 version).
  • Then you create your actions by specifying an identifier, the text of the button, and if your application should shows up when the user taps the button or if it should be executed in the background. You can also specify if the action requires to unlock the device and if the action is going to be destructive (e.g. will delete some content).
  • The next step is to create an action category that will group the actions to be displayed together for a specific context.
    • UIUserNotificationActionContextDefault is used when the notification is displayed as a modal alert.
    • UIUserNotificationActionContextMinimal is used in all the other cases: on the lock screen, in the notification center and for banner notifications.
  • Finally you register the category into the user notification settings. Note that in this example I take care to request the notification alert permission if we don't have it but the Ubudu SDK will take care of that for you if you don't do it. In this case just pass the currently registered types so you don't resign on your permissions (don't passe 0 as the types parameter!!).

The only thing you need to remember now is the identifiers you used for your actions and for your category.

Handle the actions

To handle your custom actions you need to implement the application:handleActionWithIdentifier:forLocalNotification:completionHandler: callback in your AppDelegate.

Example:

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler
{
    if ([identifier isEqualToString:@"yes"]) {
        // Handle "yes" action, forward to Ubudu SDK to execute actions linked to the notification
        [[UbuduSDK sharedInstance] executeLocalNotificationActions:notification];
    }
    else if ([identifier isEqualToString:@"no"]) {
        // Handle "no" action
    }
    else if (identifier == nil) {
        // Handle default action, don't forget to forward to Ubudu SDK
        [[UbuduSDK sharedInstance] executeLocalNotificationActions:notification];
    }
    
    // Delete the consumed notification
    [application cancelLocalNotification:notification];
    application.applicationIconBadgeNumber--;
    
    // Mandatory to call, as soon as you're done
    completionHandler();
}

Integrate with the Ubudu SDK

In order to use your custom actions with the notification created by the Ubudu SDK you will just need to indicate the identifier of your category in the JSON configuration of your local notification action.

  1. Go on https://manager.ubudu.com, sign in on go to the edition page of your beacon proximity rule.
  2. Add the actionsCategory key in the JSON configuration, right next to the alertBody key. The value must be the name of your actions category.
  3. Save the rule.

local_notification_ios8_custom_actions.png

Ubudu Pre-defined categories

The UbuduSDK provides by default some categories of actions you can use in your app.

For now the only available category is named UbuduYesNo and is configured as following:

  • Identifier: UbuduYesNo
  • 2 actions: (defined for UIUserNotificationActionContextDefault and UIUserNotificationActionContextMinimal contexts)
    • UbuduYes: title = Yes, activationMode = UIUserNotificationActivationModeForeground, not destructive
    • UbuduNo: title = No, activationMode = UIUserNotificationActivationModeBackground, not destructive, authentication not required