Oracle ADF Mobile 11.1.2.4 release adds the Push Notification Support, now ADF Mobile application can register to receive notifications through both the Apple and Google notification services. In this article I try to explain on how to implement
“Google Cloud Messaging for Android (GCM) with ADF Mobile, GCM is a service that helps developers to send data from servers to their Android applications on Android devices“.
Thanks to Joe Haung his article helped me to understand the implementation of
ADF Mobile with push notification.
Below diagram illustrates the overview working concept of ADF Mobile with Push Notification support.
[Runs with Oracle JDeveloper 11.1.2.4.0].
Registering with Google Cloud Messaging
- Open Google APIs Console page and create a new project. (If you haven’t created already otherwise it will take you to dashboard).
- After creating project, click on Overview tab. Note down the Project Number which will be used as Sender Id / Authorization Id in ADF Mobile application
- Click on Services tab on the left panel and turn on Google Cloud Messaging for Android.
- Once you are done, click on API Access and note down the API Key. This API key will be used when sending requests to GCM server.
ADF Mobile Implementation Steps
Create an ADF Mobile application, In the application controller project, register an application lifecycle event listener (ALCL) class. Open the Application Resources -> Descriptors -> ADF META-INF -> adfmf-application.xml, click on the LifeCycle Event Listener search icon and added “application.LifeCycleListenerImpl”.
Open the LifeCycleListenerImpl class and implement the
oracle.adfmf.application.PushNotificationConfig
interface. This interface provides the registration configuration for push notifications. Override and implement the
getNotificationStyle
and
getSourceAuthorizationID
methods of the
PushNotificationConfig
interface. LifeCycleListenerImpl java class looks like below.
public class LifeCycleListenerImpl implements LifeCycleListener, PushNotificationConfig {
public LifeCycleListenerImpl() {
}
public long getNotificationStyle() {
return 0L;
}
public String getSourceAuthorizationId() {
return null;
}
public void start() {
// Add code here...
}
public void stop() {
// Add code here...
}
public void activate() {
// Add code here...
}
public void deactivate() {
// Add code here...
}
}
In the application controller project, create a push notification listener class (for example,
NativePushNotificationListener
) that handles push notification events. This class must implement the oracle.adfmf.framework.event.EventListener interface that defines an event listener.
public class NativePushNotificationListener implements EventListener {
public NativePushNotificationListener() {
super();
}
public void onMessage(Event event) {
//Parsing the payload JSON string
JSONBeanSerializationHelper jsonHelper = new JSONBeanSerializationHelper();
try {
PayloadServiceResponse serviceResponse =
(PayloadServiceResponse)jsonHelper.fromJSON(PayloadServiceResponse.class, event.getPayload());
//Can access the variables like below
serviceResponse.getCustomMessage();
// To do
} catch (Exception e) {
e.printStackTrace();
}
}
public void onError(AdfException adfException) {
}
public void onOpen(String string) {
// Storing the regisration id send by GCM server in #{applicationScope.deviceToken} for further usage
ValueExpression ve = AdfmfJavaUtilities.getValueExpression("#{applicationScope.deviceToken}", String.class);
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), string);
}
}
Create a PayloadServiceResponse.java class and add the below code.
public class PayloadServiceResponse {
private double from;
private String collapse_key;
private String customMessage;
private String sound;
private String alert;
public void setFrom(double from) {
this.from = from;
}
public double getFrom() {
return from;
}
public void setCollapse_key(String collapse_key) {
this.collapse_key = collapse_key;
}
public String getCollapse_key() {
return collapse_key;
}
public void setCustomMessage(String customMessage) {
this.customMessage = customMessage;
}
public String getCustomMessage() {
return customMessage;
}
public void setSound(String sound) {
this.sound = sound;
}
public String getSound() {
return sound;
}
public void setAlert(String alert) {
this.alert = alert;
}
public String getAlert() {
return alert;
}
}
Open the LifeCycleListenerImpl class and modify the below method code as followed.
public void start() {
//Create an EventSource object that represents the source of a native push notification event:
EventSource evtSource =
EventSourceFactory.getEventSource(NativePushNotificationEventSource.NATIVE_PUSH_NOTIFICATION_REMOTE_EVENT_SOURCE_NAME);
//Create and add an object of the push notification listener class to the event source
evtSource.addListener(new NativePushNotificationListener());
}
public long getNotificationStyle() {
return 0L;
}
public String getSourceAuthorizationId() {
//Here AuthorizationId is the "Sender Id" of Google project created earlier
String senderId = "765350429141";
ValueExpression ve = AdfmfJavaUtilities.getValueExpression("#{applicationScope.applicationId}", String.class);
ve.setValue(AdfmfJavaUtilities.getAdfELContext(), senderId);
return senderId;
}
In the application controller project, click on new gallery expand the General - Data Control nodes and select
Webservice Service Data Control.
Refer to the ADF Mobile Push Notifications With Google Cloud Messaging (GCM) Part 2, set the server side code to access http://hostname/GCMService.php?wsdl
In the Create Web Service Data Control - Step 2 of 5 wizard, move the persistGCMUser from available to selected and click on Finish.
In ViewController project. Locate and expand the Application Sources
folder, then expand the META-INF folder. You will see the
adfmf-feature.xml file, click on the adfmf-feature.xml file to launch
the Feature editor. Add a new feature by clicking the green plus sign on
the Features table near top of the editor this will launch the new
Create ADF Mobile Feature dialog, modify the values as shown below.
In the Features table, select the newly created feature SaveDeviceToken. Under the
Features table, click the Content tab, and locate the Content table.
Notice that the content item SaveDeviceToken.1 is created by default. Next add a
new file by clicking the green plus sign and select ADF Mobile AMX Page option,
this will launch the new Create ADF Mobile AMX Page, modify the File Name as "SaveDeviceToken.amx".
From Data Control palette drag and drop GCMService->persistGCMUser_parameters->gcmUser as ADF Mobile Form and GCMService->persistGCMUser as ADF Mobile button as shown below.
In SaveDeviceToken.amx page, create a managed bean with action listener method (name as executePersistGCMUser) and map to persistGCMuser button action listener.
Open the SaveDeviceToken.amx and modify the page with below code.
<?xml version="1.0" encoding="UTF-8" ?>
<amx:view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amx="http://xmlns.oracle.com/adf/mf/amx"
xmlns:dvtm="http://xmlns.oracle.com/adf/mf/amx/dvt">
<amx:panelPage id="pp1">
<amx:facet name="header">
<amx:outputText value="Save Device Token" id="ot1"/>
</amx:facet>
<amx:panelFormLayout id="pfl1">
<amx:inputText value="#{bindings.username.inputValue}" label="#{bindings.username.hints.label}" id="it4"/>
<amx:inputText value="#{bindings.email.inputValue}" label="#{bindings.email.hints.label}" id="it3"/>
<amx:panelLabelAndMessage label="GCM Device Token" id="plam1">
<amx:outputText value="#{applicationScope.deviceToken}" id="ot3"/>
</amx:panelLabelAndMessage>
</amx:panelFormLayout>
<amx:commandButton actionListener="#{SaveDeviceTokenBean.executePersistGCMUser}" text="Save GCM User"
disabled="#{!bindings.persistGCMUser.enabled}" id="cb1">
<amx:setPropertyListener id="spl1" from="#{applicationScope.applicationId}"
to="#{bindings.applicationId.inputValue}" type="action"/>
<amx:setPropertyListener id="spl2" from="#{deviceScope.device.os}" to="#{bindings.deviceType.inputValue}"
type="action"/>
<amx:setPropertyListener id="spl3" from="#{applicationScope.deviceToken}"
to="#{bindings.deviceToken.inputValue}" type="action"/>
</amx:commandButton>
</amx:panelPage>
</amx:view>
Open the SaveDeviceTokenBean.java class and modify the executePersistGCMUser as shown below.
public void executePersistGCMUser(ActionEvent actionEvent) {
MethodExpression me =
AdfmfJavaUtilities.getMethodExpression("#{bindings.persistGCMUser.execute}", Object.class,
new Class[] { });
me.invoke(AdfmfJavaUtilities.getAdfELContext(), new Object[] { });
//Navigate to the Tasks feature
AdfmfContainerUtilities.gotoFeature("Tasks");
}
SaveDeviceToken.amx preview looks as below.
Open on the adfmf-feature.xml file to launch the Feature editor. Add a new feature by clicking the green plus sign on the Features table near top of the editor this will launch the new Create ADF Mobile Feature dialog, modify the values as shown below.
In the Features table, select the newly created feature Tasks. Under the Features table, click the Content tab, and locate the Content table. Notice that the content item Tasks.1 is created by default. Next add a new file by clicking the green plus sign and select ADF Mobile AMX Page option, this will launch the new Create ADF Mobile AMX Page, modify the File Name as "TasksIndexPage.amx". Page preview looks like below.
Deployed and tested the Push Notification support on both Android Device/Emulator and work's fine. If your are running the application on the emulator make sure you select target as Google APIs while creating the Android Virtual Device.
Click on the Settings icon in the emulator and go to ACCOUNTS section. Add the Google account, so that
C2DM configure with Gmail account for mapping a unique device.
Application screen looks like below when it run on Android Device/Emulator. At this stage the application would initiate a registration request with push notification services, after successful registration, GCM server issues registration id back to the android device that would uniquely identify the ADF Mobile application and the device.
Note in the first screen GCM Device Token is displayed after successful registration.
Enter form details and click save button to send back the data to application provider server, also navigates to Tasks Details screen.
Handling Push Notifications
- The ADF Mobile application is installed, but not running and ADF Mobile application is running in the background - In both the cases notification the notification message displays with the registered notification style (none, banner, or alert). When the user taps the message (if its a banner-style notification) or touches the action button (if the message appears as an alert), the ADF Mobile application launches, invoking the application notification handlers.
- The ADF Mobile application is running in the foreground - No notification message displays. The application notification handlers are invoked.
Open the http://hostname in the browser will load the index.php page and displays devices which are registered and send the message.
Refer the ADF Mobile Push Notifications With Google Cloud Messaging (GCM) Part 2, how to set the server side code to access http://hostname/index.php and send message from sever side to GCM. Once the message is sent you can see the notification in both Device/Emulator as shown below.
In the NativePushNotificationListener class - onMessage method load, you can parse the event payload and invoke additional application logic accordingly. Below is the example how the payload looks when you run in the debug mode. You can refer to NativePushNotificationListener class I have showed how to parse the payload.
[Runs with Oracle JDeveloper 11.1.2.4.0].