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-scope or 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:

  • // Instantiate a group.
    KiiGroup group = KiiGroup.createByUri(groupUri);
    
    try {
      // Refresh the group.
      group.refresh();
    } catch (GroupOperationException e) {
      // Handle the error.
    }
    
    // Instantiate a topic in the group scope.
    String topicName = "GroupTopic";
    KiiTopic topic = group.topic(topicName);
    
    // Create push message data.
    Data data = new Data();
    data.put("str", "str");
    data.put("int", 1);
    data.put("bool", false);
    data.put("double", 1.12);
    
    // Create a push message.
    KiiPushMessage message = KiiPushMessage.buildWith(data).build();
    
    try {
      // Send the push message.
      topic.sendMessage(message);
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Instantiate a group.
    KiiGroup group = KiiGroup.createByUri(groupUri);
    
    // Refresh the group.
    group.refresh(new KiiGroupCallBack() {
      @Override
      public void onRefreshCompleted(int token, KiiGroup group, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
        // Instantiate a topic in the group scope.
        String topicName = "GroupTopic";
        KiiTopic topic = group.topic(topicName);
    
        // Create push message data.
        Data data = new Data();
        data.put("str", "str");
        data.put("int", 1);
        data.put("bool", false);
        data.put("double", 1.12);
    
        // Create a push message.
        KiiPushMessage message = KiiPushMessage.buildWith(data).build();
    
        // Send the push message.
        topic.sendMessage(message, new KiiTopicCallBack() {
          @Override
          public void onSendMessageCompleted(int taskId, KiiTopic target, KiiPushMessage message, Exception exception) {
            if (exception != null) {
              // Handle the error.
              return;
            }
          }
        });
      }
    });

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

The following is the sample code.

  • try {
      // Instantiate a topic in the user scope.
      String topicName = "MyTODO";
      KiiTopic topic = KiiUser.topic(topicName);
    
      // Create push message data.
      Data data = new Data();
      data.put("Item", "Do something");
      data.put("Done", 0);
    
      // Create a push message.
      KiiPushMessage message = KiiPushMessage.buildWith(data).build();
    
      // Send the push message.
      topic.sendMessage(message);
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Instantiate a topic in the user scope.
    String topicName = "MyTODO";
    KiiTopic topic = KiiUser.topic(topicName);
    
    // Create push message data.
    Data data = new Data();
    data.put("Item", "Do something");
    data.put("Done", 0);
    
    // Create a push message.
    KiiPushMessage message = KiiPushMessage.buildWith(data).build();
    
    // Send the push message.
    topic.sendMessage(message, new KiiTopicCallBack() {
      @Override
      public void onSendMessageCompleted(int taskId, KiiTopic target, KiiPushMessage message, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
      }
    });

For both examples, here is a brief description of what is happening in the sample code:

  • Creates a push message by calling the buildWith method passing the key-value pairs to be included in the message.
  • Sends the message by calling the sendMessage method.

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

Setting fields specific to each push notification network

Sometimes you want to include field values specific to each push notification network in your push messages.

The following sample code shows how to do this.

  • // Assume that the target topic has been instantiated.
    
    // Create push message data.
    KiiPushMessage.Data data = new KiiPushMessage.Data();
    data.put("your_keys", "your_values");
    
    // Create FCM-specific data.
    GCMMessage gcm = GCMMessage.builder()
            .withCollapseKey("CollapseKey")
            .withRestrictedPackageName("your.package.name")
            .withTimeToLive(10)
            .build();
    
    // Create APNs-specific data.
    // Make the notification silent.
    APNSMessage.APNSData apnsData = new APNSMessage.APNSData();
    apnsData.put("From", "Alice");
    apnsData.put("MsgBody", "Hi all!");
    apnsData.put("Urgent", false);
    apnsData.put("Weight", 1.12);
    APNSMessage apns = APNSMessage.builder()
            .withContentAvailable(1)
            .withAPNSData(apnsData)
            .build();
    
    // Send an APNs message with rich content.
    // APNSMessage apns = APNSMessage.builder()
    //        .withAlertTitle("New message")
    //        .withAlertSubtitle("Message from Alice")
    //        .withAlertBody("It's been a while...")
    //        .withMutableContent(1)
    //        .withCategory("MESSAGE_CATEGORY")
    //        .withAPNSData(apnsData)
    //        .build();
    
    // Create MQTT-specific data.
    MqttMessage.Builder.MqttData mqttData = new MqttMessage.Builder.MqttData();
    mqttData.put("MsgTitle", "Message from Alice");
    MqttMessage mqtt = MqttMessage.builder()
            .withMqttData(mqttData)
            .build();
    
    // Create a push message.
    KiiPushMessage message = KiiPushMessage.buildWith(data)
            .withGCMMessage(gcm)
            .withAPNSMessage(apns)
            .withMqttMessage(mqtt)
            .build();
    
    try {
      // Send the push message.
      topic.sendMessage(message);
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Assume that the target topic has been instantiated.
    
    // Create push message data.
    KiiPushMessage.Data data = new KiiPushMessage.Data();
    data.put("your_keys", "your_values");
    
    // Create FCM-specific data.
    GCMMessage gcm = GCMMessage.builder()
            .withCollapseKey("CollapseKey")
            .withRestrictedPackageName("your.package.name")
            .withTimeToLive(10)
            .build();
    
    // Create APNs-specific data.
    // Make the notification silent.
    APNSMessage.APNSData apnsData = new APNSMessage.APNSData();
    apnsData.put("From", "Alice");
    apnsData.put("MsgBody", "Hi all!");
    apnsData.put("Urgent", false);
    apnsData.put("Weight", 1.12);
    APNSMessage apns = APNSMessage.builder()
            .withContentAvailable(1)
            .withAPNSData(apnsData)
            .build();
    
    // Send an APNs message with rich content.
    // APNSMessage apns = APNSMessage.builder()
    //        .withAlertTitle("New message")
    //        .withAlertSubtitle("Message from Alice")
    //        .withAlertBody("It's been a while...")
    //        .withMutableContent(1)
    //        .withCategory("MESSAGE_CATEGORY")
    //        .withAPNSData(apnsData)
    //        .build();
    
    // Create MQTT-specific data.
    MqttMessage.Builder.MqttData mqttData = new MqttMessage.Builder.MqttData();
    mqttData.put("MsgTitle", "Message from Alice");
    MqttMessage mqtt = MqttMessage.builder()
            .withMqttData(mqttData)
            .build();
    
    // Create a push message.
    KiiPushMessage message = KiiPushMessage.buildWith(data)
            .withGCMMessage(gcm)
            .withAPNSMessage(apns)
            .withMqttMessage(mqtt)
            .build();
    
    // Send the push message.
    topic.sendMessage(message, new KiiTopicCallBack() {
      @Override
      public void onSendMessageCompleted(int taskId, KiiTopic target, KiiPushMessage message, Exception exception) {
        if (exception != null) {
          // Handle the error.
          return;
        }
      }
    });
  • For adding FCM-specific fields, create a GCMMessage instance by calling the build method.
  • For adding APNs-specific fields, create an APNSMessage instance by calling the build method.
  • For adding MQTT-specific fields, create an MqttMessage instance by calling the build method.

  • When constructing a KiiPushMessage instance, include the GCMMessage, APNSMessage, and/or MqttMessage instances.

If you are going to use the silent notification feature, use the withContentAvailable() method to enable it as shown in the previous sample code. If you want to send notifications with rich content such as images to the user's iOS devices, refer to the lines that are commented out in the sample code to set the related fields.

By default, the push message will be sent to all the push notification networks. You can control message delivery by setting a flag upon construction of a KiiPushMessage instance like in the following example:

// Deliver a push message to Android devices using FCM only.
KiiPushMessage message = KiiPushMessage.buildWith(data)
        .withGCMMessage(gcm)
        .enableAPNS(false)
        .enableMqtt(false)
        .build();

// Deliver a push message to iOS devices only.
KiiPushMessage message = KiiPushMessage.buildWith(data)
        .withAPNSMessage(apns)
        .enableGCM(false)
        .enableMqtt(false)
        .build();

// Deliver a push message using MQTT only.
KiiPushMessage message = KiiPushMessage.buildWith(data)
        .withMqttMessage(mqtt)
        .enableAPNS(false)
        .enableGCM(false)
        .build();

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!".

  • // Create APNs-specific data.
    APNSMessage apns = APNSMessage.builder()
            .withAlertBody("short msg only!")
            .build();
    
    // Create a push message.
    KiiPushMessage.Data commonData = new KiiPushMessage.Data();
    KiiPushMessage message = KiiPushMessage.buildWith(commonData)
            .withAPNSMessage(apns)
            .build();
    
    try {
      // Send the push message.
      topic.sendMessage(message);
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Create APNs-specific data.
    APNSMessage apns = APNSMessage.builder()
            .withAlertBody("short msg only!")
            .build();
    
    // Create a push message.
    KiiPushMessage.Data commonData = new KiiPushMessage.Data();
    KiiPushMessage message = KiiPushMessage.buildWith(commonData)
            .withAPNSMessage(apns)
            .build();
    
    // Send the push message.
    topic.sendMessage(message, new KiiTopicCallBack() {
      @Override
      public void onSendMessageCompleted(int taskId, KiiTopic target, KiiPushMessage message, Exception exception) {
        if (exception != null) {
          // 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 topic ID 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.

  • // Create APNs-specific data.
    APNSMessage apns = APNSMessage.builder()
            .withAlertBody("Looooooooooooooooooong Message!!")
            .build();
    
    // Create a push message with the default keys suppressed.
    KiiPushMessage.Data commonData = new KiiPushMessage.Data();
    KiiPushMessage message = KiiPushMessage.buildWith(commonData)
            .sendSender(false)
            .sendObjectScope(false)
            .sendTopicId(false)
            .sendWhen(false)
            .withAPNSMessage(apns)
            .build();
    
    try {
      // Send the push message.
      topic.sendMessage(message);
    } catch (IOException ioe) {
      // Handle the error.
    } catch (AppException e) {
      // Handle the error.
    }
  • // Create APNs-specific data.
    APNSMessage apns = APNSMessage.builder()
            .withAlertBody("Looooooooooooooooooong Message!!")
            .build();
    
    // Create a push message with the default keys suppressed.
    KiiPushMessage.Data commonData = new KiiPushMessage.Data();
    KiiPushMessage message = KiiPushMessage.buildWith(commonData)
            .sendSender(false)
            .sendObjectScope(false)
            .sendTopicId(false)
            .sendWhen(false)
            .withAPNSMessage(apns)
            .build();
    
    // Send the push message.
    topic.sendMessage(message, new KiiTopicCallBack() {
      @Override
      public void onSendMessageCompleted(int taskId, KiiTopic target, KiiPushMessage message, Exception exception) {
        if (exception != null) {
          // 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