Thursday, July 24, 2014

iOS8 interactive notification available in AeroGear

AeroGear UnifiedPush Server is ready for iOS8!
Want to see how to create iOS8 interactive notifications? Follow me...

AeroDoc push notification application revisited, step by step

Last year, I blogged about AeroDoc, a demo app for AeroGear UnifiedPush Server (UPS). This is a very good entry point to get an overview on UPS. Here's the story:

A sell agent can receive push notifications triggered by her admin. Upon notification, she has the option to accept the lead and add it to her personal list. But to accept the lead, you have to tap the notification and bring the app in the foreground. The whole purpose of interactive notification is to let you do action without context switch. No more app switching!
Going back to AeroDoc tutorial, let's see how we can enhance the client app to accept a lead directly in the notification.

What you need

  • iOS8+. At the time of writing, iOS8 beta4 is out.
  • Xcode6. Same here beta4
  • clone, build and deploy UPS or alternatively create a UPS on OpenShift
  • clone, build and deploy AeroDoc backend
  • clone, build AeroDoc iOS client

  • Steps by steps

    Step1: Create an Application on UnifiedPush Server

    Watch the screencast to learn how to:
  • create an OpenShift AeroGear UPS instance.
  • create a new backend app
  • associate an iOS variant with its APNs certificate



  • Step2: AeroDoc backend configuration

    Install AeroDoc backend following instructions.
    Go to configuration link and create a new configuration, entering:
  • UPS server URL
  • AppID
  • App Secret

  • Step3: AeroDoc backend app

    AeroDoc backend app uses unifiedpush-java-client to send push notification to UPS. Since 0.8.0, unifiedpush-java-client can send interactive notification in its payload. See the extra payload line 11. The category identifier "acceptLead" should be reused when implementing actions on client side. And that's all you need to do to support interactive notification server side!
        public void sendLeads(List users, Lead lead) {
                ...
                UnifiedMessage unifiedMessage = new UnifiedMessage.Builder()
                        .pushApplicationId(getActivePushConfig().getPushApplicationId())
                        .masterSecret(getActivePushConfig().getMasterSecret())
                        .categories("lead")
                        .actionCategory("acceptLead")
                        .aliases(users)
                        .simplePush("version=" + new Date().getTime())
                        .attribute("id", lead.getId().toString())
                        .attribute("messageType", "pushed_lead")
                        .attribute("name", lead.getName())
                        .attribute("location", lead.getLocation())
                        .attribute("phone", lead.getPhoneNumber()).sound("default")
                        .alert("A new lead has been created").build();
    
                javaSender.send(unifiedMessage, new LeadSenderMessageResponseCallback());
    
        }
    

    Note: APNs interactive notifications add category to its payload to associate a group of actions to a category. As UPS already uses the name 'categories' in its payload but for a different purpose, the name action-category was chosen instead.

    Step3: AeroDoc iOS app

    Watch it live coding:



    Or just follow these instructions:

    When registering for remote notification, provide a category (from the previous code we called it 'acceptLead'). To define a category, add all associated actions. Here we demo only one action but you can define a list. Depending on your notification setup, the list of visible actions can be limited. Using UIUserNotificationActionContextMinimal you can define which actions should be displayed in priority when space is limited.
    - (UIMutableUserNotificationCategory*)registerActions {
        UIMutableUserNotificationAction* acceptLeadAction = [[UIMutableUserNotificationAction alloc] init];
        acceptLeadAction.identifier = @"Accept";
        acceptLeadAction.title = @"Accept";
        acceptLeadAction.activationMode = UIUserNotificationActivationModeForeground;
        acceptLeadAction.destructive = false;
        acceptLeadAction.authenticationRequired = false;
        
        UIMutableUserNotificationCategory* category = [[UIMutableUserNotificationCategory alloc] init];
        category.identifier = @"acceptLead";
        [category setActions:@[acceptLeadAction] forContext: UIUserNotificationActionContextDefault];
        return category;
    }
    
    Once all actions are defined and wrapped into a category, inject category to UIUserNotificationSettings as shown below:
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    #ifdef __IPHONE_8_0
        UIUserNotificationCategory* category = [self registerActions];
        NSMutableSet* categories = [NSMutableSet set];
        [categories addObject:category];
        UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:categories];
        [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    #else
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    #endif
    

    When an action has been selected in the interactive push notification, the callback application:handleActionWithIdentifier:forRemoteNotification:completionHandler: is called. To implement your action you need to check on which action was chosen:
    - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler {
        if([identifier isEqualToString: @"Accept"]) {
          ...
          ...
        }
        completionHandler();
    }
    
    You only left to implement the acceptLead logic within the if. If you want to see the full source code go to github.

    Enjoy !

    No comments:

    Post a Comment

    Note: Only a member of this blog may post a comment.