| Mobile applications / Push notifications | |
Follow this procedure to implement push notification with APNs.
The push notification solution described in this section is based on the Apple Push Notification Service. Familiarize yourself with APNs by visiting the Apple Push Notification Service web site.
Apple Push Notification service allows push servers to send notification message data to registered iOS (and OS X) devices.
The APNs service transports and routes a remote notification from a given provider to a given device. A notification is a short message built from two pieces of data: the device token and the payload.APNs provides push server and client identification. It also handles all aspects of message queuing and delivery to the target applications running on registered devices. The APNs system includes a feedback service that can be queried to check for devices that have unregistered and no longer need to be notified.
A Web Services server program maintaining the database of device tokens, with application user information. This program must listen to new device registration events, store them in a database, and from time to time query the APNs feedback service to check for unregistrations.
This program will send notification messages to the APNs server by using the com.APNS class and TCP request API. The push provider program will query the device token database to know which devices need to be notified.
Registered devices use the push notification client API to register, get notification data and unregister from the service.
iOS apps must be created with an Apple certificate for development or distribution, linked to an App ID (or Bundle ID) with push notification enabled. The provisioning profile used when building the IPA must be linked to the App ID with push enabled. Certificate, provisioning and bundle id must be specified to the GMI build tool.
To create the push provider linked to your app, usually you need to create two Apple Push Notification certificates linked to your App ID (you select the App ID when you create a push certificate in the Apple member center): One certification for development and another for distribution. For more details about the push provider certificates, see APNs SSL certificate.
Check also Apple Push Notification documentation for more details about certificate requirements for push notifications.
Each APNs client device is identified by a device token. A device token is an opaque identifier of a device that APNs gives to the device when an app registers itself for push notification. It enables APNs to locate in a unique manner the device on which the client app is installed. The device shares the device token with the push provider. The push provider must produce notification messages for each device by including the device token in the message structure.
In a notification message, the payload is a JSON-defined property list that specifies how the user of an app on a device is to be alerted.
The payload must contain a list of "aps" records. Each "aps" record represents a notification message to be displayed as a hint on the device (for example, by adding a badge number to the app icon). The "aps" records can also contain custom data in a separate set of JSON attributes.
[
{
"aps" :
{
"alert" : "My first push",
"badge" : 1,
"sound" : "default",
"content-available" : 1
}
},
{
"aps" :
{
"alert" :
{
"title" : "Push",
"body" : "My second push"
}
"badge" : 2,
"sound" : "default",
"content-available" : 1
},
"new_ids" : [ "XV234", "ZF452", "RT563" ],
"updated_ids" : [ "AC634", "HJ153" ]
}
]
With APNs, badge number handling is in charge of the application code: The push provider sends a badge number in the payload records, the app can check the message content, and must communicate with a server component, to indicate that the notification message has been consumed. The server program can then maintain a badge number for each registered device, decrementing the badge number.
In this tutorial, badge numbers are stored on the server database. The token maintainer handlers requests from apps to sync the badge number for a given device token, and the push provider program reads the database to set the badge number in the notification payload. When the app consumes messages, it queries and resets the app badge number with the getBadgeNumber/setBadgeNumber front calls, and informs the token maintainer to sync the badge number in the central database.
For each interface, use TLS (or SSL) to establish a secured communication channel. The SSL certificate required for these connections is obtained from Apple's Member Center.
To establish a TLS session with APNs, an Entrust Secure CA root certificate must be installed on the provider’s server. If the server is running OS X, this root certificate is already in the keychain. On other systems the certificate might not be available.
The Apple Push Notification Certificate identifies the push notification service for a given mobile app. This certificate will be created from an App ID (a.k.a. Bundle ID) and is used by the APNs system to dispatch the notification message to the registered devices.
For more details, see APNs SSL certificate.
To handle device registrations on the server side of your application, the same code base can be used for APNs and other token-based frameworks.
For more details, see Implementing a token maintainer.
The push provider will produce application notification messages that will be transmitted to the APNs service. The APNs service will then spread them to all registered mobile devices, identified by their device token.
To send notification messages, the push provider must build binary messages by using the com.APNS API, provided by the Web Services library, and send TCP message requests over SSL to the following URLs:
The following example demonstrates how to implement a function to send an APNs notification message. The function takes a device token and a JSON object as parameters. First, build the binary data with the com.APNS.EncodeMessage() method, then POST the data with a com.TCPRequest.doDataRequest() method. In case of success, the TCP request timeout will occur (APNs service only responds immediately in case of error), then use the com.TCPResponse.getDataResponse() method, to get status information. See com.APNS.EncodeMessage() for more details about notification message creation.
IMPORT com
IMPORT security
IMPORT util
FUNCTION apns_send_notif_http(deviceTokenHexa, notif_obj)
DEFINE deviceTokenHexa STRING,
notif_obj util.JSONObject
DEFINE req com.TCPRequest,
resp com.TCPResponse,
uuid STRING,
ecode INTEGER,
dt DATETIME YEAR TO SECOND,
exp INTEGER,
data, err BYTE,
res STRING
LOCATE data IN MEMORY
LOCATE err IN MEMORY
LET dt = CURRENT + INTERVAL(10) MINUTE TO MINUTE
LET exp = util.Datetime.toSecondsSinceEpoch(dt)
TRY
LET req = com.TCPRequest.create( "tcps://gateway.push.apple.com:2195" )
CALL req.setKeepConnection(true)
CALL req.setTimeout(2) # Wait 2 seconds for APNs to return error code
LET uuid = security.RandomGenerator.createRandomString(4)
CALL com.APNS.EncodeMessage(
data,
security.HexBinary.ToBase64(deviceTokenHexa),
notif_obj.toString(),
uuid,
exp,
10
)
IF LENGTH(data) > 2000 THEN
LET res = "ERROR : APNS payload cannot exceed 2 kilobytes"
RETURN res
END IF
CALL req.doDataRequest(data)
TRY
LET resp = req.getResponse()
CALL resp.getDataResponse(err)
CALL com.APNS.DecodeError(err) RETURNING uuid, ecode
LET res = SFMT("APNS result: UUID: %1, Error code: %2",uuid,ecode)
CATCH
CASE STATUS
WHEN -15553 LET res = "Timeout Push sent without error"
WHEN -15566 LET res = "Operation failed :", SQLCA.SQLERRM
WHEN -15564 LET res = "Server has shutdown"
OTHERWISE LET res = "ERROR :",STATUS
END CASE
END TRY
CATCH
LET res = SFMT("ERROR : %1 (%2)", STATUS, SQLCA.SQLERRM)
END TRY
RETURN res
END FUNCTION
The
next code example implements a function that creates the JSON object defining
notification content (payload). That object can be passed to the
apns_send_notif_http() function described
above:FUNCTION apns_simple_popup_notif(notif_obj, msg_title, user_data, badge_number)
DEFINE notif_obj util.JSONObject,
msg_title, user_data STRING,
badge_number INTEGER
DEFINE aps_obj, data_obj util.JSONObject
LET aps_obj = util.JSONObject.create()
CALL aps_obj.put("alert", msg_title)
CALL aps_obj.put("sound", "default")
CALL aps_obj.put("badge", badge_number)
CALL aps_obj.put("content-available", 1)
CALL notif_obj.put("aps", aps_obj)
LET data_obj = util.JSONObject.create()
CALL data_obj.put("other_info", user_data)
CALL notif_obj.put("custom_data", data_obj)
END FUNCTION
IMPORT com
IMPORT util
MAIN
DEFINE reg_ids DYNAMIC ARRAY OF STRING,
notif_obj util.JSONObject,
i INTEGER
LET notif_obj = util.JSONObject.create()
CALL gcm_simple_popup_notif(notif_obj, "This is my message!", 1)
LET reg_ids[1] = "APA91bHun..."
LET reg_ids[2] = "B4AA2q7xa..."
...
FOR i=1 TO reg_ids.getLength()
DISPLAY gcm_send_notif_http(reg_ids[i], notif_obj)
END FOR
END MAIN
FUNCTION apns_collect_tokens(reg_ids)
DEFINE reg_ids DYNAMIC ARRAY OF RECORD
token STRING,
badge INTEGER
END RECORD
DEFINE rec RECORD
id INTEGER,
sender_id VARCHAR(150),
registration_token VARCHAR(250),
badge_number INTEGER,
app_user VARCHAR(50),
reg_date DATETIME YEAR TO FRACTION(3)
END RECORD,
x INTEGER
DECLARE c1 CURSOR FOR
SELECT * FROM tokens
WHERE sender_id IS NULL -- In case if GCM tokens remain in the db
CALL reg_ids.clear()
FOREACH c1 INTO rec.*
LET x = reg_ids.getLength() + 1
LET reg_ids[x].token = rec.registration_token
LET reg_ids[x].badge = rec.badge_number
END FOREACH
END FUNCTION
FUNCTION save_badge_number(token, badge)
DEFINE token STRING,
badge INT
UPDATE tokens SET
badge_number = badge
WHERE registration_token = token
END FUNCTION
FUNCTION apns_send_message(msg_title, user_data)
DEFINE msg_title, user_data STRING
DEFINE reg_ids DYNAMIC ARRAY OF RECORD
token STRING,
badge INTEGER
END RECORD,
notif_obj util.JSONObject,
info_msg STRING,
new_badge, i INTEGER
CALL apns_collect_tokens(reg_ids)
IF reg_ids.getLength() == 0 THEN
RETURN "No registered devices..."
END IF
LET info_msg = "Send:"
FOR i=1 TO reg_ids.getLength()
LET new_badge = reg_ids[i].badge + 1
CALL save_badge_number(reg_ids[i].token, new_badge)
LET notif_obj = util.JSONObject.create()
CALL apns_simple_popup_notif(notif_obj, msg_title, user_data, new_badge)
LET info_msg = info_msg, "\n",
apns_send_notif_http(reg_ids[i].token, notif_obj)
END FOR
RETURN info_msg
END FUNCTION
See also Provider Communication with Apple Push Notification Service.
To handle push notifications in mobile apps, the same code base can be used for APNs and other token-based frameworks.
For more details see Handling notifications in the mobile app.