27 June 2012
Additional required other products
Access to the Apple iOS Provisioning Portal for your app (sign-in required)
All
Note: If you have questions about this article, use the comments feature at the bottom of the article. Please don’t contact technical support with questions about Adobe Developer Connection articles.
Learn how to leverage Apple Push Notifications in your app created with Digital Publishing Suite, Enterprise Edition to notify users of new issues becoming available and trigger Newsstand background downloads. Learn about advanced topics such as using third-party push providers, using push notifications to send messages to users, and using server scripts to schedule push notifications.
Apple Push Notifications enable app developers and publishers to send notifications to their iOS apps when the user is not currently using the app. Push notifications are often used to display a message, play a sound, and set a number in a "badge" on the apps icon. In Adobe Digital Publishing apps, a push notification can inform the user that a new issue is available, and also trigger a background download of the new issue if the app is in the iOS Newsstand.
Once a Digital Publishing Suite app is enabled and registered to receive push notifications (described below), a notification can be initiated by a push provider server (either Adobe's DPS Push Provider Server, your own server, or a third-party push provider such as Urban Airship). The notification is sent to Apple's Push Notification Service server, which then forwards the notification to the targeted app on registered devices.
Before an app can receive push notifications, it needs to register with Apple and Adobe's Push Provider Server, as shown in Figure 1.
Once an app is registered for push, push notifications are sent to the app as shown in Figure 2.
The push notification is initiated in Folio Producer as shown in Figure 3. The Adobe DPS Push Provider sends the notification "content-available:1", which indicates that new content is available for this app/viewer.
After receiving the push, a viewer app enabled for Apple Newsstand will initiate a background download via the following process:
renewAuthToken and getEntitlements ). (See Direct Entitlement article for more information.)For push and background downloading to function, a series of things are required.
The following is required for push notifications to be possible:
<dict>
<key>application-identifier</key>
<string>W8E2YLRAWL.com.adobe.sdreier.dpsdev</string>
<key>aps-environment</key>
<key>get-task-allow</key>
<false/>
<key>keychain-access-groups</key>
<array>
<string>W8E2YLRAWL.*<string>
</array>
</dict>
A background download is the automatic download and installation of a folio into the application's library. Upon successful download, the cover screen in the Newsstand application will be updated to the new folio and a blue sash will be displayed over the upper-right corner (see Figure 4).
The following is required for background downloading to work:
Publishers requiring periodic notifications can do so with an API exposed by Adobe's fulfillment service. This is uniquely important to daily publishers, for which fidelity to a schedule must be maintained so as to not run afoul of Apple's 24-hour limitation. (Background downloads are limited to approximately once every 24 hours)
The following sample provides a programmatic method of sending Newsstand notification messages. Text alerts displayed on the user's device are not supported at this time by Adobe's push service; however, see following sections about how to integrate a third-party push server that can support this.
URL (HTTP POST): http://lighthouse.adobe.com/dps/push/notify.php
Parameters: adobeID, password, productId
Table 1 explains the parameters of this method.
Table 1. Parameters of the HTTP POST method for sending Newsstand notifications
| Parameter | Format | Descriptions |
adobeID |
emailAddress |
The AdobeID corresponding to the fulfillment account for the targeted application. |
password |
The password for the above. | |
productId |
string |
The published Product ID for which a push notification should be sent. Note: At the moment, only the most recently published folio will be background-downloaded. |
Using CURL and cron, it is possible to automate this method:
CURL Usage:
> curl -d "adobeid=<youradobeid>" -d "password=<yourpassword>" -d "productid=<a_product_id>" -X POST http://lighthouse.adobe.com/dps/push/notify.php
Or, you can send the Newsstand notify via this webform that Adobe is providing for your use.
Figure 5 illustrates this method:
Once everything is in place, follow these steps to test your implementation of push notifications and Newsstand background downloading:
Note: Development builds of viewers connect to Apple’s APNS system via the sandbox. Because Adobe’s push server is connected via the production channel to Apple APNS, you will need to create a special productId to test on a development build. Using a productId that begins with ‘dev_test.’, you can use Adobe’s Folio Producer to send a Notify to your development viewer.
You can also use a third-party push provider such as Urban Airship. This may give you more flexibility and add capabilities such as the ability to send messages to users via push notifications. Publishers can leverage Urban Airship's basic notification framework within Adobe DPS applications with minimal effort.
Visit the Urban Airship site to see more information about Urban Airship's offerings and to sign up for their service.
You must host PHP files on a publicly accessible server and have a valid account at Urban Airship.
$user : Urban Airship Application Key$pass : Urban Airship Application Secret or Master SecretThe uaregister.txt file contains a JSON payload that will be sent along with the device registration to UA. The only required property is an alias . Please create your own.
You must create your own Urban Airship account and provision it with a proper APNS certificate from the iOS Provisioning Portal.
To send a text message, enter one at index.html and press Send Notify Now. You can send as many messages as you like.
For background downloading to work, note that:
Beginning with release 18, enterprise publishers can replace Adobe DPS's APNS server with their own implementation (for example, java-apns). This allows publishers to send text messages and to use any commercially available provider for push.
Two main processes are required to push: Registration and Notification. This document will greatly simplify these processes. For additional information, please see the Apple Push Notification Service.
Whenever an APNS-enabled, customized viewer is activated, it attempts to register with its APNS provider. This registration is sent as a multi-part HTTP POST with the parameters shown in Table 2:
Table 2. Parameters for the registration HTTP POST method
| Property | value(s) | Description |
newsstandEnabled |
0 | 8 | Registers for Newsstand notifications (8) or not (0) |
badgeEnabled |
1 | Registers for badge updates. |
accountId |
<GUID> |
Uniquely identifies the account that owns this viewer |
tokenType |
"production" | "test" |
AppStore distribution ( "production" ) or development build ( "test" ) |
token |
<encodedToken> |
Apple encoded version of the "devId". This is to be used for all communications with APNS. |
soundEnabled |
2 | Only default sounds are supported |
devId |
<UUID> |
Application specific identifier for the device. |
|
|
Describes the dimensions of the device registering for push notification. |
alertEnabled |
4 | Registers for generic alert. Note: Alerts are never sent by Adobe DPS APNS |
Sample PHP registration code:
<?php
include 'settings.php';
// get base64 encoded device token from POST message
$token = $_POST['token'];
$token = $_POST['newsstandEnabled'];
// Get binary token value
$decodedToken = base64_decode($token);
// Convert to a 64 character string representation
$hexToken = "";
for ($i = 0; $i < 32; $i++) {
$hexToken = $hexToken . bin2hex($decodedToken[$i]);
}
error_log("hexToken:" . $hexToken);
?>
Sample Java registration code:
package com.adobe.sdreier.push;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.tomcat.util.http.fileupload.*;
import sun.misc.BASE64Decoder;
/**
* Servlet implementation class register
*/
public class Register extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
String deviceId="";
String token="";
Boolean soundEnabled=false;
Boolean alertEnabled=false;
Boolean badgeEnabled=false;
if (request.getContentType().indexOf(FileUploadBase.MULTIPART_FORM_DATA)>=0) {
try {
DiskFileUpload upload = new DiskFileUpload();
List items = upload.parseRequest(request);
Iterator itr = items.iterator();
while(itr.hasNext()) {
FileItem item = (FileItem) itr.next();
// check if the current item is a form field or an uploaded file
if(item.isFormField()) {
// get the name of the field
String fieldName = item.getFieldName();
if (fieldName.compareTo("devId")==0) {
deviceId = item.getString();
}
else
if (fieldName.compareTo("token")==0) {
token = item.getString();
}
else
if (fieldName.compareTo("badgeEnabled")==0) {
badgeEnabled = item.getString().compareTo("0")!=0;
}
else
if (fieldName.compareTo("soundEnabled")==0) {
soundEnabled = item.getString().compareTo("0")!=0;
}
else
if (fieldName.compareTo("alertEnabled")==0) {
alertEnabled = item.getString().compareTo("0")!=0;
}
}
}
}
catch(Exception e) {
}
}
else {
deviceId = request.getParameter("devId");
token = request.getParameter("token");
badgeEnabled = request.getParameter("badgeEnabled").compareTo("0")!=0;
soundEnabled = request.getParameter("soundEnabled").compareTo("0")!=0;
alertEnabled = request.getParameter("alertEnabled").compareTo("0")!=0;
}
System.out.println("device: "+deviceId);
System.out.println("token : "+token);
System.out.println("badge : "+badgeEnabled);
System.out.println("sound : "+soundEnabled);
System.out.println("alert : "+alertEnabled);
BASE64Decoder decoder = new BASE64Decoder();
byte[] decodedBytes = decoder.decodeBuffer(token);
String tokenString="";
for (Integer i=0; i<decodedBytes.length; i++) {
//System.out.println("Token["+i+"] = "+Integer.toHexString(decodedBytes[i]));
tokenString += Integer.toHexString((decodedBytes[i] >> 4)&0xf);
tokenString += Integer.toHexString (decodedBytes[i] &0xf);
}
//Database db = new Database();
//db.insertDevice(new Device(deviceId, tokenString, soundEnabled, alertEnabled, badgeEnabled) );
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
doGet(request, response);
}
}
APNS messaging is an Apple iOS–level feature. Only in the case of Newsstand notification will the viewer participate in the notification. All messages should be formatted as JSON packages. For examples, please see Examples of JSON Payload in the Apple Developer Center.
Table 3. Parameters for APNS messages
| Property | value | description |
alert |
<string> |
The text message to display to the user. No localization arguments are supported. |
badge |
<number> |
If non-zero, it displays the number on the icon of the application. If zero, no number is displayed. |
content-available |
0 | 1 | Non-zero indicates a Newsstand push message. The receipt of this will wake the viewer to begin a background download. See Notes. |
sound |
"default" |
Only the default notification sound is supported. |
productID |
<string> |
Product. |
See the following information on push notifications from Apple:
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.