Sending a Push Notification

When a topic is set, we are ready to send a message to the topic. The message sent to the topic will be pushed to the topic subscribers.

Sending a push message to an application-scope topic

Only an application developer can send a push message to an application scope topic on the developer portal.

See Sending a Push to User Notification to learn how the application developer can push messages.

Sending a push message to a group and user-scope topic

Sending a message

Any group member can send a push message to a group-scope topic.

Let's explore how to do this in the following sample code. In this sample code, the push message will be sent to the FCM, APNs, and MQTT networks.

Swift:

  • // Instantiate a group.
    let group = KiiGroup(uri: groupUri)
    
    do{
      // Refresh the group.
      try group.refreshSynchronous()
    } catch let error as NSError {
      // Handle the error.
      return
    }
    
    // Instantiate a topic in the group scope.
    let topicName = "GroupTopic"
    let topic = group.topic(withName: topicName)
    
    // Create a container of APNs-specific data.
    let apnsFields = KiiAPNSFields.create()
    
    // Make the notification silent.
    apnsFields.contentAvailable = 1
    
    // This sample code sends a silent notification,
    // so the title, subtitle, and body keys are not set.
    // apnsFields.alertTitle = "New message"
    // apnsFields.alertSubtitle = "Message from Alice"
    // apnsFields.alertBody = "It's been a while..."
    
    // Define the category.
    // apnsFields.category = "MESSAGE_CATEGORY"
    
    // Let the implemented Notification Service Extension or
    // Notification Content Extension process the message.
    // apnsFields.mutableContent = 1
    
    // Create push message data.
    var data = [AnyHashable: Any]()
    data["str"] = "str"
    data["int"] = NSNumber(value: 1 as Int)
    data["bool"] = NSNumber(value: false as Bool)
    data["double"] = NSNumber(value: 1.12 as Double)
    
    // Create a push message.
    let message = KiiPushMessage.composeMessage(with: data)
    message.apnsFields = apnsFields
    
    do{
      // Send the push message.
      try topic.sendMessageSynchronous(message)
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Instantiate a group.
    let group = KiiGroup(uri: groupUri)
    
    // Refresh the group.
    group.refresh { (group : KiiGroup?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
    
      // Instantiate a topic in the group scope.
      let topicName = "GroupTopic"
      let topic = group!.topic(withName: topicName)
    
      // Create a container of APNs-specific data.
      let apnsFields = KiiAPNSFields.create()
    
      // Make the notification silent.
      apnsFields.contentAvailable = 1
    
      // This sample code sends a silent notification,
      // so the title, subtitle, and body keys are not set.
      // apnsFields.alertTitle = "New message"
      // apnsFields.alertSubtitle = "Message from Alice"
      // apnsFields.alertBody = "It's been a while..."
    
      // Define the category.
      // apnsFields.category = "MESSAGE_CATEGORY"
    
      // Let the implemented Notification Service Extension or
      // Notification Content Extension process the message.
      // apnsFields.mutableContent = 1
    
      // Create push message data.
      var data = [AnyHashable: Any]()
      data["str"] = "str"
      data["int"] = NSNumber(value: 1 as Int)
      data["bool"] = NSNumber(value: false as Bool)
      data["double"] = NSNumber(value: 1.12 as Double)
    
      // Create a push message.
      let message = KiiPushMessage.composeMessage(with: data)
      message.apnsFields = apnsFields
    
      // Send the push message.
      topic.send(message, with: { (topic , error : Error?) -> Void in
        if error != nil {
          // Handle the error.
          return
        }
      })
    }

Objective-C:

  • NSError *error = nil;
    
    // Instantiate a group.
    KiiGroup *group = [KiiGroup groupWithURI:groupUri];
    
    // Refresh the group.
    [group refreshSynchronous:&error];
    if (error != nil) {
      // Handle the error.
      return;
    }
    
    // Instantiate a topic in the group scope.
    NSString *topicname = @"GroupTopic";
    KiiTopic *topic = [group topicWithName:topicname];
    
    // Create a container of APNs-specific data.
    KiiAPNSFields *apnsFields = [KiiAPNSFields createFields];
    
    // Make the notification silent.
    [apnsFields setContentAvailable:@1];
    
    // This sample code sends a silent notification,
    // so the title, subtitle, and body keys are not set.
    // [apnsFields setAlertTitle:@"New message"];
    // [apnsFields setAlertSubtitle:@"Message from Alice"];
    // [apnsFields setAlertBody:@"It's been a while..."];
    
    // Define the category.
    // [apnsFields setCategory:@"MESSAGE_CATEGORY"];
    
    // Let the implemented Notification Service Extension or
    // Notification Content Extension process the message.
    // [apnsFields setMutableContent:@1];
    
    // Create push message data.
    NSMutableDictionary *data = [NSMutableDictionary dictionary];
    data[@"str"]=@"str";
    data[@"int"]=[NSNumber numberWithInt:1];
    data[@"bool"]=@YES;
    data[@"double"]=[NSNumber numberWithDouble:1.12];
    
    // Create a push message.
    KiiPushMessage *message = [KiiPushMessage composeMessageWithData:data];
    message.apnsFields = apnsFields;
    
    // Send the push message.
    [topic sendMessageSynchronous:message
                        withError:&error];
    
    if (error != nil) {
      // Handle the error.
      return;
    }
  • // Instantiate a group.
    KiiGroup *group = [KiiGroup groupWithURI:groupUri];
    
    // Refresh the group.
    [group refreshWithBlock:^(KiiGroup *group, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
    
      // Instantiate a topic in the group scope.
      NSString *topicname = @"GroupTopic";
      KiiTopic *topic = [group topicWithName:topicname];
    
      // Create a container of APNs-specific data.
      KiiAPNSFields *apnsFields = [KiiAPNSFields createFields];
    
      // Make the notification silent.
      [apnsFields setContentAvailable:@1];
    
      // This sample code sends a silent notification,
      // so the title, subtitle, and body keys are not set.
      // [apnsFields setAlertTitle:@"New message"];
      // [apnsFields setAlertSubtitle:@"Message from Alice"];
      // [apnsFields setAlertBody:@"It's been a while..."];
    
      // Define the category.
      // [apnsFields setCategory:@"MESSAGE_CATEGORY"];
    
      // Let the implemented Notification Service Extension or
      // Notification Content Extension process the message.
      // [apnsFields setMutableContent:@1];
    
      // Create push message data.
      NSMutableDictionary *data = [NSMutableDictionary dictionary];
      data[@"str"]=@"str";
      data[@"int"]=[NSNumber numberWithInt:1];
      data[@"bool"]=@YES;
      data[@"double"]=[NSNumber numberWithDouble:1.12];
    
      // Create a push message.
      KiiPushMessage *message = [KiiPushMessage composeMessageWithData:data];
      message.apnsFields = apnsFields;
    
      // Send the push message.
      [topic sendMessage:message
             withBlock:^(KiiTopic *topic, NSError *error) {
        if (error != nil) {
          // Handle the error.
          return;
        }
      }];
    }];

Here is a brief description of what is happening in the sample code.

  • Create an instance of the APNs message fields by calling the createFields method.
  • If you are using the silent notification, set 1 in the contentAvailable property. If you are not using the silent notification, set the title in the alertTitle property, the subtitle in the alertSubtitle property, and the body in the alertBody property as needed.
  • If you are sending categorized push notification (iOS 8 support), just set the category property with category identifier that you have already registered on your apps (See Initializing the actionable notification for more details).
  • If you are sending push notifications with images and custom UI based on the rich notification feature introduced with iOS 10, set 1 in the mutableContent property. If you use the rich notification feature, add a Notification Content Extension and a Notification Service Extension to your project so that your mobile app can properly handle received push notifications.
  • Create a push message by calling the composeMessageWithData: method and assigning the message body to it.
  • Send the message by calling the sendMessageSynchronous:withError: or sendMessage:withBlock: method.

For a user-scope topic, only the user who owns the topic can send a push message to it.

The refresh(_:) method is executed in the sample code. You can omit this method if you use the group just for sending a push message.

Let's explore how to do this in the following sample code. In this sample code, the push message will be sent to APNs only.

Swift:

  • // Instantiate a topic in the user scope.
    let user = KiiUser.current()!
    let topicName = "MyToDO"
    let topic = user.topic(withName: topicName)
    
    // Create a container of APNs-specific data.
    let apnsFields = KiiAPNSFields.create()
    
    // Create APNs-specific data.
    var dictionary = [AnyHashable: Any]()
    dictionary["item"] = "Do Something"
    dictionary["Done"] = NSNumber(value: 1 as Int32)
    apnsFields.setSpecificData(dictionary)
    
    // Make the notification silent.
    apnsFields.contentAvailable = 1
    
    // This sample code sends a silent notification,
    // so the body key is not set.
    // apnsFields.alertBody = "Show Message"
    
    // Create a push message.
    let message = KiiPushMessage.composeMessage(with:nil)
    
    // Disable FCM and MQTT so that the message will not be sent to devices using FCM or MQTT.
    message.setGCMEnabled(false)
    message.setMQTTEnabled(false)
    message.apnsFields = apnsFields
    
    do{
      // Send the push message.
      try topic.sendMessageSynchronous(message)
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Instantiate a topic in the user scope.
    let user = KiiUser.current()!
    let topicName = "MyToDO"
    let topic = user.topic(withName: topicName)
    
    // Create a container of APNs-specific data.
    let apnsFields = KiiAPNSFields.create()
    
    // Create APNs-specific data.
    var dictionary = [AnyHashable: Any]()
    dictionary["item"] = "Do Something"
    dictionary["Done"] = NSNumber(value: 1 as Int32)
    apnsFields.setSpecificData(dictionary)
    
    // Make the notification silent.
    apnsFields.contentAvailable = 1
    
    // This sample code sends a silent notification,
    // so the body key is not set.
    // apnsFields.alertBody = "Show Message"
    
    // Create a push message.
    let message = KiiPushMessage.composeMessage(with:nil)
    
    // Disable FCM and MQTT so that the message will not be sent to devices using FCM or MQTT.
    message.setGCMEnabled(false)
    message.setMQTTEnabled(false)
    message.apnsFields = apnsFields
    
    // Send the push message.
    topic.send(message, with: { (topic , error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
    })

Objective-C:

  • NSError *error = nil;
    
    // Instantiate a topic in the user scope.
    KiiUser* user = [KiiUser currentUser];
    NSString *topicname = @"MyTODO";
    KiiTopic *topic = [user topicWithName:topicname];
    
    // Create a container of APNs-specific data.
    KiiAPNSFields *apnsFields = [KiiAPNSFields createFields];
    
    // Create APNs-specific data.
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    [dictionary setObject:@"Do Something"
                   forKey:@"Item"];
    [dictionary setObject:[NSNumber numberWithInt:1]
                   forKey:@"Done"];
    [apnsFields setSpecificData:dictionary];
    
    // Make the notification silent.
    [apnsFields setContentAvailable:@1];
    
    // This sample code sends a silent notification,
    // so the body key is not set.
    // [apnsFields setAlertBody:@"Show message"];
    
    // Create a push message.
    KiiPushMessage *message = [KiiPushMessage composeMessageWithData:nil];
    
    // Disable FCM and MQTT so that the message will not be sent to devices using FCM or MQTT.
    [message setGCMEnabled:NO];
    [message setMQTTEnabled:NO];
    message.apnsFields = apnsFields;
    
    // Send the push message.
    [topic sendMessageSynchronous:message
                        withError:&error];
    if (error != nil) {
      // Handle the error.
      return;
    }
  • // Instantiate a topic in the user scope.
    KiiUser* user = [KiiUser currentUser];
    NSString *topicname = @"MyTODO";
    KiiTopic *topic = [user topicWithName:topicname];
    
    // Create a container of APNs-specific data.
    KiiAPNSFields *apnsFields = [KiiAPNSFields createFields];
    
    // Create APNs-specific data.
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    [dictionary setObject:@"Do Something"
                   forKey:@"Item"];
    [dictionary setObject:[NSNumber numberWithInt:1]
                   forKey:@"Done"];
    [apnsFields setSpecificData:dictionary];
    
    // Make the notification silent.
    [apnsFields setContentAvailable:@1];
    
    // This sample code sends a silent notification,
    // so the body key is not set.
    // [apnsFields setAlertBody:@"Show message"];
    
    // Create a push message.
    KiiPushMessage *message = [KiiPushMessage composeMessageWithData:nil];
    
    // Disable FCM and MQTT so that the message will not be sent to devices using FCM or MQTT.
    [message setGCMEnabled:NO];
    [message setMQTTEnabled:NO];
    message.apnsFields = apnsFields;
    
    // Send the push message.
    [topic sendMessage:message
             withBlock:^(KiiTopic *topic, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
    }];

Here is a brief description of what is happening in the sample code.

  • Create an instance of the APNs message fields by calling the createFields method.
  • Set user-defined fields by creating a dictionary, setting key-value pairs and by calling the setSpecificData: method.
  • If you are using the silent notification, set a flag with the setContentAvailable: method. If you are not using the silent notification, set APNs Alert property in the APNs message by calling the setAlertBody: method as needed.
  • Create a push message by calling the composeMessageWithData: method. Send the push message only to APNs by setting the argument of the setGCMEnabled method and the setMQTTEnabled method to false. To block message delivery to APNs, use the setAPNSEnabled method.
  • Send the message by calling the sendMessageSynchronous:withError: or sendMessage:withBlock: method.

Saving the APNs payload

The FCM service allows you to use the payload up to 4 KB (4096 bytes) while the APNs payload is limited to 2 KB (2048 bytes).

Kii Cloud adds some predefined keys in the push notification message by default. For example, let us assume that we are going to send an APNs message with its alert body property "short msg only!".

Swift:

  • // Create APNs-specific data.
    let apnsFields = KiiAPNSFields.create()
    apnsFields.alertBody = "short message only"
    
    // Create a push message.
    let message = KiiPushMessage.composeMessage(withData:nil)
    message.apnsFields = apnsFields
    message.setGCMEnabled(false)
    message.setMQTTEnabled(false)
    
    do{
      // Send the push message.
      try topic.sendMessageSynchronous(message)
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Create APNs-specific data.
    let apnsFields = KiiAPNSFields.create()
    apnsFields.alertBody = "short message only"
    
    // Create a push message.
    let message = KiiPushMessage.composeMessage(withData:nil)
    message.apnsFields = apnsFields
    message.setGCMEnabled(false)
    message.setMQTTEnabled(false)
    
    // Send the push message.
    topic.send(message, with: { (topic , error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
    })

Objective-C:

  • NSError *error = nil;
    
    // Create APNs-specific data.
    KiiAPNSFields *apnsFields = [KiiAPNSFields createFields];
    [apnsFields setAlertBody:@"short msg only!"];
    
    // Create a push message.
    KiiPushMessage *pushMessage = [KiiPushMessage composeMessageWithData:nil];
    pushMessage.apnsFields = apnsFields
    
    // Send the push message.
    [topic sendMessageSynchronous:pushMessage
                        withError:&error];
    if (error != nil) {
      // Handle the error.
      return;
    }
  • // Create APNs-specific data.
    KiiAPNSFields *apnsFields = [KiiAPNSFields createFields];
    [apnsFields setAlertBody:@"short msg only!"];
    
    // Create a push message.
    KiiPushMessage *pushMessage = [KiiPushMessage composeMessageWithData:nil];
    pushMessage.apnsFields = apnsFields
    [pushMessage setGCMEnabled:NO];
    [pushMessage setMQTTEnabled:NO];
    
    // Send the push message.
    [topic sendMessage:pushMessage
             withBlock:^(KiiTopic *topic, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
    }];

Here is an actual APNs message that will be sent. You will notice that some default keys are included in the message.

{
  aps = {
    alert = {
      body = "short msg only!";
    };
  };
  s = "cf6de5b5-8927-48a4-a410-xxxxxxxxxxxx";
  sa = 9a2385ce;
  st = "APP_AND_USER";
  su = "e26ad504-8100-4056-b3d3-xxxxxxxxxxxx";
  to = "MyTopic";
  w = 1373623307000;
}

Here is a list of the default keys:

  • s: The user ID of the sender of the push message.
  • sa: The AppID of the application that send the push message.
  • st: The scope of the topic to which the push message was sent.
    • "APP" if the topic has the application scope.
    • "APP_AND_GROUP" if the topic has the group scope.
    • "APP_AND_USER" if the topic has the user scope.
  • sg: The ID of the group to which the topic belongs (apply only if the topic has the group scope).
  • su: The user ID of the owner who owns the topic (apply only if the topic has the user scope).
  • to: The TopicId of the topic to which the push message was sent.
  • w: The time when the push message was sent (UNIX time in milliseconds, UTC)

When you want to send a long message, you can suppress these default keys so as to save the APNs payload. See the following sample code to see how you can suppress them.

Swift:

  • // Create APNs-specific data.
    let apnsFields = KiiAPNSFields.create()
    apnsFields.alertBody = "Looooooooooooooooooong Message!!"
    
    // Create a push message with the default keys suppressed.
    let message = KiiPushMessage.composeMessage(withData:nil)
    message.apnsFields = apnsFields
    message.sendSender = NSNumber(value: false as Bool)
    message.sendWhen = NSNumber(value: false as Bool)
    message.sendTopicID = NSNumber(value: false as Bool)
    message.sendObjectScope = NSNumber(value: false as Bool)
    
    do{
      // Send the push message.
      try topic.sendMessageSynchronous(message)
    } catch let error as NSError {
      // Handle the error.
      return
    }
  • // Create APNs-specific data.
    let apnsFields = KiiAPNSFields.create()
    apnsFields.alertBody = "Looooooooooooooooooong Message!!"
    
    // Create a push message with the default keys suppressed.
    let message = KiiPushMessage.composeMessage(withData:nil)
    message.apnsFields = apnsFields
    message.sendSender = NSNumber(value: false as Bool)
    message.sendWhen = NSNumber(value: false as Bool)
    message.sendTopicID = NSNumber(value: false as Bool)
    message.sendObjectScope = NSNumber(value: false as Bool)
    
    // Send the push message.
    topic.send(message, with: { (topic , error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
    })

Objective-C:

  • NSError *error = nil;
    
    // Create APNs-specific data.
    KiiAPNSFields *apnsFields = [KiiAPNSFields createFields];
    [apnsFields setAlertBody:@"Looooooooooooooooooong Message!!"];
    
    // Create a push message with the default keys suppressed.
    KiiPushMessage *pushMessage = [KiiPushMessage composeMessageWithData:nil];
    pushMessage.apnsFields = apnsFields;
    [pushMessage setSendSender:[NSNumber numberWithBool:NO]];
    [pushMessage setSendWhen:[NSNumber numberWithBool:NO]];
    [pushMessage setSendTopicID:[NSNumber numberWithBool:NO]];
    [pushMessage setSendObjectScope:[NSNumber numberWithBool:NO]];
    
    // Send the push message.
    [topic sendMessageSynchronous:pushMessage
                        withError:&error];
    if (error != nil) {
      // Handle the error.
      return;
    }
  • // Create APNs-specific data.
    KiiAPNSFields *apnsFields = [KiiAPNSFields createFields];
    [apnsFields setAlertBody:@"Looooooooooooooooooong Message!!"];
    
    // Create a push message with the default keys suppressed.
    KiiPushMessage *pushMessage = [KiiPushMessage composeMessageWithData:nil];
    pushMessage.apnsFields = apnsFields;
    [pushMessage setSendSender:[NSNumber numberWithBool:NO]];
    [pushMessage setSendWhen:[NSNumber numberWithBool:NO]];
    [pushMessage setSendTopicID:[NSNumber numberWithBool:NO]];
    [pushMessage setSendObjectScope:[NSNumber numberWithBool:NO]];
    
    // Send the push message.
    [topic sendMessage:pushMessage
             withBlock:^(KiiTopic *topic, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
    }];

The above code will send the following push message.

{
  aps = {
    alert = {
      body = "Looooooooooooooooooong Message!!";
    };
  };
}

To suppress the default keys, call the following methods with the parameter false when you create a KiiPushMessage instance.

Key to suppress Corresponding method
s setSendSender
sa, st, sg, su setSendObjectScope
to setSendTopicID
w setSendWhen