-
Notifications
You must be signed in to change notification settings - Fork 409
Push Notifications
This chapter discusses push support in Codename One applications. It covers how to set up push on the various platforms, how to respond to push notifications in your app, and how to send push notifications to your app.
Note
|
Push notifications require a Codename One Pro account or higher. |
Push notifications provide a way to inform users that something of interest has taken place. It is one of the few mechanisms available to interact with the user even when the app isn’t running. If your app is registered to receive push notifications, then you can send messages to the user’s device via REST API either from another device, or, as is usually the case, from a web server.
Messages may contain a short title and text body that will be displayed to the user in their device’s messages stream. They may also specify a badge to display on the app’s icon (e.g. that red circle on your mail app icon that indicates how many unread messages you have), a sound to play then the message arrives, an image attachment, and a set of "actions" that the user can perform directly in the push notification.
In addition to messages that the user sees, a push notification can contain non-visual information that is silently sent to your app.
Enabling push support in your application is just a matter of implementing the PushCallback
interface in your application’s main class (i.e. the class that includes your start()
, init()
, etc… methods.
public class MyApplication implements PushCallback {
// ....
/**
* Invoked when the push notification occurs
*
* @param value the value of the push notification
*/
public void push(String value) {
System.out.println("Received push message: "+value);
}
/**
* Invoked when push registration is complete to pass the device ID to the application.
*
* @param deviceId OS native push id you should not use this value and instead use <code>Push.getPushKey()</code>
* @see Push#getPushKey()
*/
public void registeredForPush(String deviceId) {
System.out.println("The Push ID for this device is "+Push.getPushKey());
}
/**
* Invoked to indicate an error occurred during registration for push notification
* @param error descriptive error string
* @param errorCode an error code
*/
public void pushRegistrationError(String error, int errorCode) {
System.out.println("An error occurred during push registration.");
}
}
There will be additional steps required to deploy to each platform (e.g. iOS requires you to generate push certificates, Android needs you to register your app ID with their cloud messaging platform, etc…), but, fundamentally, this is all that is required to enable push support in your app.
Let’s take minute to go over the three callbacks in our application.
Registration
When your application first opens, it needs to register with the platform’s central cloud messaging infrastructure. On Android this involves a call to their GCM/FCM server; on iOS, the call will be to the APNS server, on Windows (UWP) the call will be to the WNS server. And so on. That server will return a unique device ID that can be used to send push notifications to the device. This device ID will then be passed to your registeredForPush()
method as the deviceId
parameter so that you can save it somewhere. Typically you would send this value to your own web service so that you can use it to send notifications to the device later on. The device ID will generally not change unless you uninstall and reinstall the app, but you will receive the callback every time the app starts.
Important
|
The deviceId parameter cannot be used directly when sending push messages via the Codename One push service. It needs to be prefixed with a platform identifier so the that push server knows which messaging service to route the message through. You can obtain the complete device ID, including the platform prefix, by calling Push.getPushKey() .
|
If the registration failed for some reason, the the pushRegistrationError()
callback will be fired instead.
Notice that all of this happens seamlessly behind the scenes when your app loads. You don’t need to initiate any of this workflow.
Sending a Push Notification
Codename One provides a secure REST API for sending push notifications. As an HTTP API, it is language agnostic. You can send push notifications to your app using Java, PHP, Python, Ruby, or even by hand using something like curl. Each HTTP request can contain a push message and a list of device IDs to which the message should be sent. You don’t need to worry about whether your app is running on Android, iOS, Windows, or the web. A single HTTP request can send a message to many devices at once.
Receiving a Push Notification
There are two different scenarios to be aware of when it comes to receiving push notifications. If your app is running in the foreground when the message arrives, then it will be passed directly to your push()
callback. If your app is either in the background, or not running, then the notification will be displayed in your device’s notifications. If the user then taps the notification, it will open your app, and the push()
callback will be run with the contents of the message.
Some push message types include hidden content that will not be displayed in your device’s notifications. These hidden messages (or portions of messages) are passed directly to the push()
callback of your app for processing.
Note
|
On iOS, hidden push messages (push type 2) will not be delivered when the app is in the background. |
The easiest way to test push notifications in your app is to use the push simulation feature of the Codename One Simulator.
The "Registered Successfully" button will trigger your app’s registeredForPush()
method, and the "Registration Error" button will trigger your app’s pushRegistrationError()
method.
The "Send" button will trigger the push()
callback with the message body that you place in the "Send Message" field.
The "Push Type" drop-down allows you to select the "type" of the push message. This dictates how the message body (i.e. the contents of the "Send Message" field) is interpreted. Some push types simply pass the message to the device verbatim, while others assume that the message contains structure that is meant to be parsed by the client to extract such things as badges, sounds, images, and actions that are associated with the message. We’ll go over the available push types in a moment, but for now, we’ll keep it simple by just using a push type of "1" - which just sends the message verbatim.
Let’s try a simple "hello world" push message. Select "1" from the "Push Type" drop-down menu, and enter "Hello World" into the "Send Message" field as shown above. Then press "send".
Assuming your push()
method looks like:
public void push(String value) {
System.out.println("Received push message: "+value);
}
You should see the following output in your console:
Received push message: Hello World
This experiment simulated a push notification while the app is running in the foreground. Now let’s simulate the case where the app is not running, or running in the background. We can simulate this by pausing the app. Return to the Codename One simulator window, and select "Pause App" from the "Simulate" menu as shown below.
When the app is paused it will simply display a white screen in the simulator with the text "Paused" in the middle.
Now return to the push simulator again, and press "Send" again with same values in the other fields (Push type 1, and Message "Hello World"). Rather than running the push()
callback this time, it will display a popup dialog outside the app, as shown below.
While this popup dialog doesn’t replicate what a push notification will look like in a device’s notifications stream when the app is closed, it does simulate the conceptual workflow. The process whereby the user is notified of the message outside of the app, and the app is not notified until/unless the user taps on the notification.
If you monitor the console for your app, you should notice that the push()
callback hasn’t been called yet for this notification, but if you click "OK" in the dialog, your push()
callback will be run. Clicking OK is analogous to the user tapping on the notification. If you simply close the dialog box (by clicking the "x" in the corner), this would be analogous to the user dismissing the notification. In this case the push()
callback would not be called at all.
The example above sends a simple message to be displayed to the user. Push notifications can include more data than just an alert message, though. When the selected "push type" is 0 or 1, the push server will interpret the message body a simple alert string. Selecting a different push type will affect how the message body is interpreted. The following push types are supported:
-
0
,1
- The default push types, they work everywhere and present the string as the push alert to the user -
2
- hidden, non-visual push. This won’t show any visual indicator on any OS!
In Android this will trigger the push(String) call with the message body. In iOS this will only happen if the application is in the foreground otherwise the push will be lost -
3
-1 + 2 = 3
allows combining a visual push with a non-visual portion. Expects a message in the form:This is what the user won’t see;This is something he will see
. E.g. you can bundle a special ID or even a JSON string in the hidden part while including a friendly message in the visual part.
When active this will trigger the push(String) method twice, once with the visual and once with the hidden data. -
4
- Allows splitting a visual push request based on the formattitle;body
to provide better visual representation in some OS’s. -
5
- Sends a regular push message but doesn’t play a sound when the push arrives -
99
- The message body is expected to be XML, where the root element contains at leasttype
andbody
attributes which correspond to one of the other push push types and message body respectively. This push type supports additional information such as image attachments and push actions. E.g.<push type="1" body="Hello World"/>
-
100
- Applicable only to iOS and Windows. Allows setting the numeric badge on the icon to the given number. The body of the message must be a number e.g. unread count. -
101
- identical to 100 with an added message payload separated with a space. E.g.30 You have 30 unread messages
will set the badge to "30" and present the push notification text of "You have 30 unread messages".
The following sections will show examples of the various kinds of pushes. You can try them out yourself by opening the push simulator.
Push Type 1; Message Body: "Hello World"
In all cases, if the user taps/clicks the notification, it will bring the app to the foreground and call the push()
callback with "Hello World" as the argument.
Push Type 2; Message Body: "Hello World"
Push type 2 is a hidden push so it will behave differently on different platforms. On Android, the push()
callback will be fired even if the app is in the background. On iOS, it will simply be ignored if the app is in the background.
If the app is in the foreground, this will trigger the push()
callback with "Hello World" as the argument.
Tip
|
You can determine the the type of push that has been received in your push() callback by calling Display.getInstance().getProperty("pushType") . This will return a String of the push type. E.g. in this case Display.getInstance().getProperty("pushType") will return "2".
|
Push Type 3; Message Body Hello World;{"from":"Jim", "content":"Hello World"}
Push type 3 combines an alert message with some hidden content that the user won’t see. In the example above, the alert message is "Hello World" and the hidden content is a JSON string that will be passed to our app to be parsed.
If the app is in the background, then the alert message will be posted to the user’s notifications. See "Example Push Type 1" above as this message will be identical.
This push will result in our push()
callback being fired twice; once with the alert message, and once with the hidden content. When it is fired with the alert message, Display.getInstance().getProperty("pushType")
will report a type of "1". When it is fired with the JSON hidden content, it will report a push type of "2".
Push Type 4; Message Body "Hello World;I’m just saying hello"
Push type 4 specifies a title and a message body. In this example, alert title will be "Hello World", and the body will by "I’m just saying hello".
With this push type, the push()
callback will be fired only if the user taps/opens the notification, and the argument will contain the entire message ("Title;Body").
Note
|
On some platforms, the argument of the push() callback will only include the "body" portion of the payload, and in other platforms it will include the full "Title;Body" payload.
|
Push Type 5; Message Body "Hello World"
Push type 5 will behave identically to push type 1, except that the notification won’t make any sound on the device. On some platforms, Display.getInstance().getProperty("pushType")
will report a push type of "1", when it receives a push of type 5.
Push Type 100; Message Body "5"
Push type 100 just expects an integer in the message body. This is interpreted as the badge that should be set on the app. This is currently only supported on Windows and iOS.
Push type 100 should not trigger the push()
callback.
Push Type 101; Message Body "5 Hello World"
Push type 101 combines a badge with an alert message. The badge number should be the first thing in the payload, followed by a space, and the remainder is the alert message.
On platforms that do not support badges (e.g. Android), Push type 101 will behave exactly as push type 1, except that the badge prefix will be stripped from the message.
The push()
callback will be called only if the user taps the notification. Display.getInstance().getProperty("pushType")
will return "1" for this type.
Rich push notifications refer to push notifications that include functionality above and beyond simply displaying an alert message to the user. Codename One’s support for rich notifications includes image attachments and push actions.
When you attach an image to a push notification, it will appear as a large image in the push notification on the user’s device if that device supports it. iOS supports image attachments in iOS 10, Android supports them in API 26. The Javascript port, and Windows (UWP) port do not currently support image attachments. If a platform that doesn’t support image attachments receives a push notification with an image attachment, it will just ignore it.
Push type "99" is used to send rich push notifications. It is sort of a "meta" push type, or a "container", as it can be used to send any of the other push types, but to attach additional content, such as image attachments.
The message body should be an XML string. A minimal example of a push type 99 that actually sends a push type 1, which message "Hello World", but with an attached image is:
<push type="1" body="Hello World"><img src="https://exmaple.com/myimage.jpg"/></push>
Important
|
The image URL must be a secure URL (i.e. start with "https:" and not "http:", otherwise, iOS will simply ignore it. |
Note
|
The image will only be shown if you press and pull down on the notification. When the notification initially appears in the user’s notifications it will appear like a normal alert - but possibly with the image shown as a small thumbnail. |
The push()
callback will receive "Hello World" as its argument and Display.getInstance().getProperty("pushType")
will return "1" in this example.
You can access additional information about the push content using the com.codename1.push.PushContent
class, as follows:
public void push(String message) {
PushContent content = PushContent.get();
if (content != null) {
String imageUrl = content.getImageUrl();
// The image attachment URL in the push notification
// or `null` if there was no image attachment.
}
}
Warning
|
Make sure to only call PushContent.get() once inside your push() callback, and store the return value. PushContent.get() works like a queue of size=1, and it pops off the item from the front of the queue when it is called. If you call it twice, the second time will return null .
|
When you include actions in a push notification, the user will be presented with buttons as part of the notification on supported platforms. E.g. if the notification is intended to invite the user to an event, you might want to include buttons/actions like "Attending", "Not Attending", "Maybe", so that the user can respond quickly to the notification and not necessarily have to open your app.
You can determine whether the user has pressed a particular button on the notification using the `PushContent.getActionId()` method inside your `push()` callback.
How it works
Your app defines which action categories it supports, and associates a set of actions with each category. If a push notification includes a "category" attribute, then the notification will be presented with the associated actions manifested as buttons.
Defining the Categories and Actions
You can specify the available categories and actions for your app by implementing the com.codename1.push.PushActionsProvider
interface in your app’s main class.
E.g.
import com.codename1.push.PushAction;
import com.codename1.push.PushActionCategory;
import com.codename1.push.PushActionsProvider;
...
public class MyApplication implements PushCallback, PushActionsProvider {
...
@Override
public PushActionCategory[] getPushActionCategories() {
return new PushActionCategory[]{
new PushActionCategory("invite", new PushAction[]{
new PushAction("yes", "Yes"),
new PushAction("no", "No"),
new PushAction("maybe", "Maybe")
})
};
}
}
In the above example, we create only a single category, "invite" that has actions "yes", "no", and "maybe".
Sending a Push Notification with "invite" Category
Now we can test our new category. In the push simulator, you can select Push Type "99", with the message body:
<push type="1" body="Would you like to come to a party?" category="invite"/>
The push()
callback will be fired after the user taps on the notification, or one of its actions. If the user taps the notification itself, and not one of the actions, then your PushContent.getActionId()
will return null
. If they selected one of the actions, then the action ID of that action can be obtained from getActionId()
.
The category of the notification will be made available via the getCategory()
method of PushContent
.
E.g.
public void push(String message) {
PushContent content = PushContent.get();
if (content != null) {
if ("invite".equals(content.getCategory())) {
if (content.getActionId() != null) {
System.out.println("The user selected the "+content.getActionid()+" action");
} else {
System.out.println("The user clicked on the invite notification, but didn't select an action.");
}
}
}
}
=== Deploying Push-Enabled Apps to Device
So, you've implemented the Push callback in your app, and tested it in the push simulator and it works. If you try to deploy your app to a device, you may be disappointed to discover that your app doesn't seem to be receiving push notifications when installed on the device. This is because each platform has its own bureaucracy and hoops that you have to jump through before they will deliver notifications to your app. Read on to find out how to satisfy their requirements.
[[push-bureaucracy-android-section]]
==== The Push Bureaucracy - Android
TIP: To set the push icon place a 24x24 icon named `ic_stat_notify.png` under the `native/android` folder of the app. The icon can be white with transparency areas
Android Push goes thru Google servers and to do that we need to register with Google to get keys for server usage.
We need two important values: `GCM_SENDER_ID` & `GCM_SERVER_API_KEY`. The former is used in the client and the latter value is used to push from the server code.
// HTML_ONLY_START
To generate these values we need a Google cloud project. We go over the process of generating a cloud project in the Google+ login section https://www.codenameone.com/manual/misc-features.html#google-login-section[here].
// HTML_ONLY_END
////
//PDF_ONLY
To generate these values we need a Google cloud project. We go over the process of generating a cloud project in the Google+ login section <<google-login-section, here>>.
////
To generate those just go to https://developers.google.com/mobile/add and click #pick a platform#:
.Click "pick a platform"
image::img/developer-guide/chat-app-tutorial-gcm-1.png[Click "pick a platform"]
Select #Android App#
.Select "Android App"
image::img/developer-guide/chat-app-tutorial-gcm-2.png[Select "Android App"]
NOTE: Google introduced support for sending GCM messages to iOS applications, this has nothing to do with the iOS native push we discuss below
Enter the details for the app and the package
.Enter the details for the app and the package
image::img/developer-guide/chat-app-tutorial-gcm-3.png[Enter the details for the app and the package]
Click the #Cloud Messaging# option then click the #Enable Google Cloud Messaging# button
.Click the "Cloud Messaging" option then click the "Enable Google Cloud Messaging" button
image::img/developer-guide/chat-app-tutorial-gcm-4.png[Click the "Cloud Messaging" option then click the "Enable Google Cloud Messaging" button]
You should now have the values for both `GCM_SENDER_ID` & `GCM_SERVER_API_KEY` as illustrated below. Notice that the sender id is the numeric key whereas the api key is the alpha-numeric key:
.You should now have the values for both `GCM_SENDER_ID` & `GCM_SERVER_API_KEY`
image::img/developer-guide/chat-app-tutorial-gcm-5.png[You should now have the values for both `GCM_SENDER_ID` & `GCM_SERVER_API_KEY`]
Now, in your Codename One project, you should add the `gcm.sender_id` build hint with the value of your `GCM_SENDER_ID`
e.g.
gcm.sender_id=<YOUR GCM_SENDER_ID>
NOTE: The `gcm.sender_id` build was added after the Codename One 3.6 release. If you are performing a versioned build for 3.6 or earlier, this build hint will be ignored. [[push-bureaucracy-ios-section]] ==== The Push Bureaucracy - iOS Push on iOS is much harder to handle than the Android version, however we simplified this significantly with the certificate wizard. iOS push needs two additional P12 certificates. IMPORTANT: Please *notice* that these are *NOT* the signing certificates! + They are *completely different certificates* that have nothing to do with the build process! The certificate wizard can generate these additional push certificates and do quite a few other things if you just check this flag in the end of the wizard: .Enable Push in the certificate wizard image::img/developer-guide/certificate-wizard-enable-push.png[Enable Push in the certificate wizard,scaledwidth=40%] IMPORTANT: If you already have signing certificated defined for your app just skip the certificate generation phase (answer no) the rest will work as usual. You can then install the push certificates locally and use them later on but there is an easier way. You need to host the push certificates in the cloud so they will be reachable by the push servers, Codename One that for you seamlessly. + Once you go thru the wizard you should get an automated email containing information about push and the location of the push certificates, it should start like this:
iOS Push certificates have been created for your app with bundle ID com.mycompany.myapp.mypushdemo. Please file this email away for safe keeping as you will need the details about the certificate locations and passwords to use Push successfully in your apps.
Development Push Certificate URL: https://codename-one-push-certificates.s3.amazonaws.com/com.mycompany.myapp.mypushdemo_DevelopmentPush_LONG_UNIQUE_KEY.p12
Development Push Certificate Password: ssDfdsfer324
Production Push Certificate URL: https://codename-one-push-certificates.s3.amazonaws.com/com.mycompany.myapp.mypushdemo_ProductionPush_LONG_UNIQUE_KEY.p12
Production Push Certificate Password: ssDfdsfer324
The URL's and passwords are everything that you will need later on to get push working on iOS. Notice that the wizard also performs a couple of other tasks specifically it sets the `ios.includePush` build hint to true & adds push to the provisioning profile etc. // HTML_ONLY_START You can read more about the certificate wizard in the https://www.codenameone.com/manual/signing.html[signing section]. // HTML_ONLY_END //// //PDF_ONLY You can read more about the certificate wizard in the <<signing-section-top-heading,signing section>> //// [[push-bureaucracy-uwp-section]] ==== The Push Bureaucracy - UWP (Windows 10) Push on UWP requires only that you register your app in the Windows Store Dashboard. You will then be provided with credentials (Package Security Identifier (SID) and a secret key) that you can use to send push notifications to your app. To begin this process, go to the https://developer.microsoft.com/en-us/windows[Windows Dev Center] and select "Dashboard". // HTML_ONLY_START You can read more about the registering your app in the Windows store https://www.codenameone.com/manual/appendix-uwp.html#building-for-the-windows-store[here]. // HTML_ONLY_END //// //PDF_ONLY You can read more about the registering your app in the Windows store <<building-for-the-windows-store,here>> //// Once you have registered your app in the Windows Store, and completed the corresponding setup in Codename One settings (e.g. generated a certificate), you should proceed to configure your app for push notifications. Navigate to the App overview page for your app inside the Windows store dashboard. Under the "Services" menu (left side), select "Push notifications". .Push notifications menu item in Windows Store dashboard image::img/developer-guide/windows-store-push-notications-menu.png[Push notifications menu item in Windows Store dashboard,scaledwidth=10%] Then, select the "WNS/MPNS" option that appears in the left menu under "Push notifications" .WNS menu item in Windows Store dashboard image::img/developer-guide/windows-store-wns-menu-item.png[WNS menu item in Windows Store dashboard,scaledwidth=10%] This will bring you to a page with information about WNS push notifications. You'll be interested in the paragraph shown here: .Live services link image::img/developer-guide/wns-live-services-link.png[Live services link,scaledwidth=20%] Click on the "Live Services Site" link. You'll be prompted to log in using your Windows Store account. Then you'll be taken to a page that contains the push credentials that you can use for sending push messages to your app. You'll be interested in two values: Package SID. (It will be of the form "ms-app://XXXXXXXXXXX...") .WNS Package SID image::img/developer-guide/wns-package-id.png[WNS Package SID,scaledwidth=20%] Client Secret. This will be listed in a section called "Application Secrets" .WNS Client secret image::img/developer-guide/wns-client-secret.png[WNS Client secret,scaledwidth=20%] You will use these two values for sending push notifications to your app. Microsoft provides full instructions on setting up WNS notifications https://msdn.microsoft.com/library/windows/apps/hh465407[here] but much of this is not relevant for Codename One apps. For Codename One apps, one need only obtain Package Security ID and client secret values for the app. [[push-bureaucracy-javascript-section]] ==== The Push Bureaucracy - Javascript Codename One apps support push in browsers that implement the Web Push API. At time of writing, this list includes: * Firefox (Version 50) * Chrome (Version 49) * Opera (Version 42) * Chrome for Android (Version 56) Push support is currently under development in MS Edge, so should also be available soon. Firefox doesn't require any special setup for Push. If your main class implements the `PushCallback` interface, it should *just work*. Chrome uses GCM for its push notifications - the same system that Android uses. The directions for setting up a GCM account are the same as provided <<push-bureaucracy-android-section,here>>, and you can reuse the same `GCM_SENDER_ID` and `GCM_SERVER_KEY` values. You need to add the `gcm.sender_id` build hint so that the GCM_SENDER_ID will be added to the app's manifest file:
gcm.sender_id=GCM_SENDER_ID
Where `GCM_SENDER_ID` is your GCM_SENDER_ID. NOTE: Push support requires that your app be served over https with a valid SSL certificate. It will not work with the "preview" version of your app. You'll need to download the .zip or .war file and host the file on your own site - with a valid SSL certificate. === Sending Push Messages You can send a push message in many ways e.g. from another device or any type of server but there are some values that you will need regardless of the way in which you send the push message. [source,java] ----- private static final String PUSH_TOKEN = "********-****-****-****-*************"; ----- The push token is a unique "key" that you can use to send push thru your Codename One account. It allows you to send push messages without placing your Codename One email or password into your source files. You can get it by going to the Codename One build server dashboard at https://www.codenameone.com/build-server.html and selecting the #Account# tab. The token should appear at the bottom as such: .Push Token from the build server image::img/developer-guide/push-token.png[Push Token from the build server] The instructions for extracting the API key for Google are <<push-bureaucracy-android-section,listed above>>. [source,java] ----- private static final String GCM_SERVER_API_KEY = "******************-********************"; ----- The instructions for extracting the SID and Client Secret for Windows are <<push-bureaucracy-uwp-section,listed above>>. [source,java] ----- private static final String WNS_SID = "ms-app://**************************************"; private static final String WNS_CLIENT_SECRET = "*************************"; ----- When sending push to iOS devices we have two modes: - Production - Distribution This allows you to debug the push related functionality without risking the possibility of sending a push into a production app. Its important to send the values to the right server during development/production. [source,java] ----- private static final boolean ITUNES_PRODUCTION_PUSH = false; ----- iOS needs a certificate in order to send a push, this allows you to prove to Apples push servers that you are who you claim to be (the author of the app). IMPORTANT: These are not the signing certificates and are completely separate from them! You can obtain these two certificates (for development/appstore) via the certificate wizard as <<push-bureaucracy-ios-section,explained above>>. [source,java] ----- private static final String ITUNES_PRODUCTION_PUSH_CERT = "https://domain.com/linkToP12Prod.p12"; private static final String ITUNES_PRODUCTION_PUSH_CERT_PASSWORD = "ProdPassword"; private static final String ITUNES_DEVELOPMENT_PUSH_CERT = "https://domain.com/linkToP12Dev.p12"; private static final String ITUNES_DEVELOPMENT_PUSH_CERT_PASSWORD = "DevPassword"; ----- ==== Sending a Push Message From Codename One While normally sending a push message to a device should involve a server code there might be cases (e.g. instant messaging/social) where initiating a push from one client to another makes sense. To simplify these use cases we added the https://www.codenameone.com/javadoc/com/codename1/push/Push.html[Push] API. To use the `Push` API you need the device key of the destination device to which you want to send the message. You can get that value from the `Push.getPushKey()` method. Notice that you need that value from the *destination device* and not the local device! To send a message to another device just use: [source,java] ----- String cert = ITUNES_DEVELOPMENT_PUSH_CERT; String pass = ITUNES_DEVELOPMENT_PUSH_CERT_PASSWORD; if(ITUNES_PRODUCTION_PUSH) { cert = ITUNES_PRODUCTION_PUSH_CERT; pass = ITUNES_PRODUCTION_PUSH_CERT_PASSWORD; } new Push(PUSH_TOKEN, "Hello World", deviceKey) .apnsAuth(cert, pass, ITUNES_PRODUCTION_PUSH) .gcmAuth(GCM_SERVER_API_KEY) .wnsAuth(WNS_SID, WNS_CLIENT_SECRET) .send(); ----- The "builder" style API used in the above sample was added post Codename One 3.6 to facilitate the addition of new Push services. If you are building against Codename one 3.6 or earlier, you should use the static `Push.sendPushMessage()` instead as shown below: [source,java]
Push.sendPushMessage(PUSH_TOKEN, "Hello World", ITUNES_PRODUCTION_PUSH, GCM_SERVER_API_KEY, cert, pass, 1, deviceKey));
This will send the push message "Hello World" to the device with the key `deviceKey`. The `1` argument represents the standard push message type, we discuss push message types <<push-message-types-section,below>>. ==== Sending Push Message From A Java or Generic Server Sending a push message from the server is a more elaborate affair and might require sending push messages to many devices in a single batch. We can send a push message as an HTTP `POST` request to https://push.codenameone.com/push/push[https://push.codenameone.com/push/push]. That URL accepts the following arguments: - *token* - your developer token to identify the account sending the push - `PUSH_TOKEN` - *device* - one or more device keys to send the push to. You can send push to up to 500 devices with a single request - - *type* - the message type identical to the old set of supported types in the old push servers - *body* - the body of the message - *auth* - the Google push auth key - `GCM_SERVER_API_KEY` (also used for sending to Chrome Javascript Apps) - *production* - `true`/`false` whether to push to production or sandbox environment in iOS - `ITUNES_PRODUCTION_PUSH` - *certPassword* - password for the push certificate in iOS push - `ITUNES_DEVELOPMENT_PUSH_CERT_PASSWORD` or `ITUNES_PRODUCTION_PUSH_CERT_PASSWORD` - *cert* - http or https URL containing the push certificate for an iOS push - `ITUNES_DEVELOPMENT_PUSH_CERT` or `ITUNES_PRODUCTION_PUSH_CERT` - *sid* - The package security ID (SID) for UWP apps. - *client_secret* - The client secret for UWP apps. We can thus send a push from Java EE using code like this: [source,java] ----- HttpURLConnection connection = (HttpURLConnection)new URL("https://push.codenameone.com/push/push").openConnection(); connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); String cert = ITUNES_DEVELOPMENT_PUSH_CERT; String pass = ITUNES_DEVELOPMENT_PUSH_CERT_PASSWORD; if(ITUNES_PRODUCTION_PUSH) { cert = ITUNES_PRODUCTION_PUSH_CERT; pass = ITUNES_PRODUCTION_PUSH_CERT_PASSWORD; } String query = "token=" + PUSH_TOKEN + "&device=" + URLEncoder.encode(deviceId1, "UTF-8") + "&device=" + URLEncoder.encode(deviceId2, "UTF-8") + "&device=" + URLEncoder.encode(deviceId3, "UTF-8") + "&type=1" + "&auth=" + URLEncoder.encode(GCM_SERVER_API_KEY, "UTF-8") + "&certPassword=" + URLEncoder.encode(pass, "UTF-8") + "&cert=" + URLEncoder.encode(cert, "UTF-8") + "&body=" + URLEncoder.encode(MESSAGE_BODY, "UTF-8") + "&production=" + ITUNES_PRODUCTION_PUSH + "&sid=" + URLEncoder.encode(WNS_SID, "UTF-8") + "&client_secret=" + URLEncoder.encode(WNS_CLIENT_SECRET, "UTF-8"); try (OutputStream output = connection.getOutputStream()) { output.write(query.getBytes("UTF-8")); } int c = connection.getResponseCode(); // read response JSON ----- Notice that you can send a push to 500 devices. To send in larger batches you need to split the push requests into 500 device batches. ===== Server JSON Responses The push servers send responses in JSON form. It's crucial to parse and manage those as they might contain important information. If there is an error that isn't fatal such as quota exceeded etc. you will get an error message like this: [source,javascript] ----- {"error":"Error message"} ----- A normal response, will be an array with results: [source,javascript] ----- [ {"id"="deviceId","status"="error","message"="Invalid Device ID"}, {"id"="cn1-gcm-nativegcmkey","status"="updateId", "newId"="cn1-gcm-newgcmkey"}, {"id"="cn1-gcm-okgcmkey","status"="OK"}, {"id"="cn1-gcm-errorkey","status"="error","message"="Server error message"}, {"id"="cn1-ios-iphonekey","status"="inactive"}, ] ----- There are several things to notice in the responses above: - If the response contains `status=updateId` it means that the GCM server wants you to update the device id to a new device id. You should do that in the database and avoid sending pushes to the old key - iOS doesn't acknowledge device receipt but it does send a `status=inactive` result which you should use to remove the device from the list of devices IMPORTANT: APNS (Apple's push service) returns uppercase key results. This means that code for managing the keys in your database must be case insensitive TIP: Apple doesn't always send back a result for a device being inactive and might fail silently
About This Guide
Introduction
Basics: Themes, Styles, Components & Layouts
Theme Basics
Advanced Theming
Working With The GUI Builder
The Components Of Codename One
Using ComponentSelector
Animations & Transitions
The EDT - Event Dispatch Thread
Monetization
Graphics, Drawing, Images & Fonts
Events
File-System,-Storage,-Network-&-Parsing
Miscellaneous Features
Performance, Size & Debugging
Advanced Topics/Under The Hood
Signing, Certificates & Provisioning
Appendix: Working With iOS
Appendix: Working with Mac OS X
Appendix: Working With Javascript
Appendix: Working With UWP
Security
cn1libs
Appendix: Casual Game Programming