NNAClientExample MIDlet uses the Nokia Notifications Client API to register and receive notifications on device. It can be used as a reference to write your own notification MIDlets.
You can download the project files for the MIDlet from the download page.
You need the following to develop this MIDlet:
Nokia Asha SDK 1.0 or newer
The Example MIDlet consists of the following classes:
Main—The MIDlet main class.
MainView—Implements functionality to use Nokia Notification Client API.
Check out the usage of Nokia Notifications Client API in the client example:
Importing Nokia Notifications Installer classes
Checking and updating Notification Enabler
Importing Nokia Notifications API classes
Opening the session by specifying Application ID and Service ID
Registering the MIDlet to get notifications
Retrieving the Notification ID
Receiving notifications
Unregistering from notification
Handling various notification error and state changes.
These classes need to be imported for managing the installation of the Notification Enabler:
import com.nokia.notifications.installer.InstallListener; import com.nokia.notifications.installer.InstallerFactory; import com.nokia.notifications.NotificationsEnablerInstaller;
The Main class implements the com.nokia.notifications.installer.InstallListener. The installForm variable is needed to make the downloading, installation and error handling visible for the user:
public class Main extends MIDlet implements InstallListener { Form installForm;
NotificationsEnablerInstaller is responsible for keeping track of updating of the Notification Enabler:
public void startApp() { . . . // Check the availability of Notification Enabler NotificationsEnablerInstaller installer = InstallerFactory.getInstaller(); Installer.checkAndUpdateNapiEnabler(this, installForm, this);
The installResult call-back method is called for letting the MIDlet know the status of downloading and installation:
// Implements for InstallListener interface Public void installResult(int result) { if (InstallerListener.INSTALLATION_OK == result || InstallerListener.ALREADY_EXISTS == result) { Display.getDisplay(this).setCurrent(new MainView(this)); } else { installForm.append(new StringItem(“Error”, “Installation failed with code “ + result)); } }
These import statements declare the Nokia Notifications API interface visible for the code.
import com.nokia.notifications.NotificationError; import com.nokia.notifications.NotificationException; import com.nokia.notifications.NotificationInfo; import com.nokia.notifications.NotificationMessage; import com.nokia.notifications.NotificationSession; import com.nokia.notifications.NotificationSessionFactory; import com.nokia.notifications.NotificationSessionListener; import com.nokia.notifications.NotificationState;
In the code below, the default Application ID is "com.example", which can be used to send notifications from the Developer Console to the example client MIDlet.
OpenSession makes the session between the example MIDlet and the Notification Enabler established. This needs to be done before the RegisterApplication method can be called.
try { session = NotificationSessionFactory.openSession( main, // The MIDlet instance "example.com", // Service ID (Deprecated) "com.example", // Application ID this); // NotificationSessionListener } catch (NotificationException ne) { addLogMessage(ERROR, ne.toString()); }
As an exercise you can replace the default Service ID and Application ID values to try out your own service credentials. You can send push notifications to your MIDlet easily from the Developer Console (only in sandbox environment). When you try out the example MIDlet remember to install the Environment Selector MIDlet, switch the used environment to "Sandbox" and boot the device before you try to send a push notifications..
To register to make the MIDlet receive notifications the registerApplication method must be called. When the session state changes, the control of the execution is moved into the stateChanged method.
try { session.registerApplication(); } catch (NotificationException ne) { addLogMessage(ERROR, ne.toString()); }
It is mandatory to call registerApplication method every time when the MIDlet is launched to make the MIDlet able to receive notifications.
Your MIDlet needs to retrieve the Notification ID to be able to tell it to your service. Then your service uses it to address the notifications correctly to your MIDlet. The Notification ID is requested by the client MIDlet and then sent to the service, as shown below.
Sending the Notification ID to the service takes place outside of the Notifications Server. The Nokia Notifications API does not provide a mechanism to send the Notification ID to the service. To retrieve the Notification ID you need to call getNotificationInformation() method on the session object. It is an asynchronous method call, and infoReceived() call back method is called with Notification ID.
In case of bad network the returned NID may be empty. If that happens, you just have to try again.
try { session.getNotificationInformation(); } catch (NotificationException ne) { addLogMessage(ERROR, ne.toString()); }
Notification Enabler calls infoReceived method when the Notification ID becomes available. A way how the Notification ID is sent to the service is up to service developer (you may use for example, an HTTP request).
public void infoReceived(NotificationInfo info) { String notificationId = info.getNotificationId(); if (notificationId.length() == 0) { addLogMessage(ERROR, "Received notification ID is empty!"); } else { addLogMessage(NOTIFICATION_ID, notificationId); System.out.println("Notification ID :-" + notificationId); }
Notification Enabler calls messageReceived() method when there is an incoming notification. If the MIDlet is running then this method is called directly without showing the notification banner on notification panel.
public void messageReceived(NotificationMessage message) { addLogMessage(NOTIFICATION_MESSAGE, message.getPayload().getData()); }
Calling unregister method makes the MIDlet go into offline state and it cannot receive notifications. unregister() method is an asynchronous method. When execution of it is finished then stateChanged() call back method is called by the Notification Enabler.
Never call unregister method for your own MIDlet unless you really want that no notifications will be sent/received to/by your MIDlet. It is a good idea to include unregistration call into your MIDlet's settings so that the end-user can decide if he/she wants to receive notifications or not.
try { session.unregisterApplication(); } catch (NotificationException ne) { addLogMessage(ERROR, ne.toString()); }
Notification Enabler calls stateChanged() method whenever there is any change in the notification State of Notification Enabler or there is some error condition. The developer must ensure the MIDlet handles all possible state change events and error conditions to provide the best possible user experience for their MIDlets.
public void stateChanged(NotificationState state) { switch (state.getSessionState()) { case NotificationState.STATE_OFFLINE: deleteAll(); removeCommand(unregisterCommand); removeCommand(cancelCommand); addCommand(registerCommand); addLogMessage(STATUS, "Offline"); break; case NotificationState.STATE_CONNECTING: deleteAll(); removeCommand(registerCommand); addCommand(cancelCommand); addLogMessage(STATUS, "Connecting"); break; case NotificationState.STATE_ONLINE: deleteAll(); removeCommand(registerCommand); removeCommand(cancelCommand); addCommand(getIdCommand); addCommand(unregisterCommand); addLogMessage(STATUS, "Online"); break; default: addLogMessage(STATUS, "Unknown"); break; } final int error = state.getSessionError(); if (error != NotificationError.ERROR_NONE) { addLogMessage(ERROR, notificationStateErrorCodeToString(error)); }
All possible error has been described in API reference and developer can debug their MIDlets based on the errors provided by Notification Enabler.
Please note, that not all real life errors can be reproduced on SDK Emulator. However, your MIDlet must still handle those error conditions which may not be occurring on SDK Emulator but can happen on device.
List of errors which are commonly not reproduced on SDK Emulator but happen on real device include:
ERROR_CONNECTION_DISABLED_BY_USER
ERROR_DISABLED_BY_USER
ERROR_NO_NETWORK
private String notificationStateErrorCodeToString(final int errorCode) { String errorMessage = null; switch (errorCode) { case NotificationError.ERROR_APPLICATION_ID_CONFLICT: errorMessage = "The Application ID has already been registered by another MIDlet."; break; case NotificationError.ERROR_APPLICATION_ID_INVALID: errorMessage = "The Application ID is either empty or more than 255 characters long."; break; case NotificationError.ERROR_AUTHENTICATION_FAILED: errorMessage = "The device is not able to fetch the authentication details from the Notification server."; break; case NotificationError.ERROR_CONNECTION_DISABLED_BY_USER: errorMessage = "The user has disabled connections like WiFi and cellular network."; break; case NotificationError.ERROR_DISABLED_BY_USER: errorMessage = "The user has disabled notifications."; break; case NotificationError.ERROR_NO_NETWORK: errorMessage = "The Notification Enabler has lost connection with the Notification server."; break; case NotificationError.ERROR_NONE: errorMessage = "No error."; break; case NotificationError.ERROR_NOT_ALLOWED: errorMessage = "NotificationSession is not in correct state."; break; case NotificationError.ERROR_NOT_KNOWN: errorMessage = "Other Notification error."; break; case NotificationError.ERROR_NOT_REGISTERED: errorMessage = "MIDlet is not registered, but is calling for a function that requires registration."; break; case NotificationError.ERROR_REGISTER_FAILED: errorMessage = "Registration failed because there is not enough space available in the device memory to store the settings."; break; case NotificationError.ERROR_SERVICE_UNAVAILABLE: errorMessage = "Notification Server is not available."; break; case NotificationError.ERROR_SESSION_CLOSED: errorMessage = "NotificationSession function call failed because session was closed."; break; default: errorMessage = "Unknown error."; break; } return errorMessage; }