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.
- Go on https://manager.ubudu.com, sign in
on go to the edition page of your beacon proximity rule.
- Add the actionsCategory key in the JSON
configuration, right next to the alertBody key.
The value must be the name of your actions category.
- Save the rule.
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