One of the new features in version 2.1.1. of Oracle MAF are local notifications.
These notifications originate within the MAF application and are received by the same application. They are delivered to the end user through standard mechanisms supported by the mobile device platform (for example, banner, sound) and can work when the application is either in the foreground, background or not running at all.
I this post I show you an example of how to work with Local Notifications from Java. I use a simple MAF app. I will not explain how to build this app, but the source can be downloaded here. It is mainly derived from the "LocalNotificationDemo" public sample app.
Introducing Local Notifications
As with many framework features, MAF supports three ways to set Local Notifications. First you can use the device features datacontrol. To support declarative use of Local Notifications, the DeviceFeatures data control includes the addLocalNotification and cancelLocalNotification methods, which enable MAF applications to leverage a device's interface for managing notifications so end users can schedule or cancel local notifications.
Second you have the option to set Local Notifications from JavaScript. MAF allows you to manage local notifications using JavaScript APIs in the adf.mf.api.localnotification namespace. The methods add() and cancel() are available. More info on this is available from the developer guide (see resources at the end of this post).
Finally you can set Local Notifications from Java code, which is what I will explain in the remaining part of this post.
Set up the Listening Part
Because the Listening part is the same for all methods mentioned above I will start to explain this before going into detail for setting Local Notifications from Java code.
The concept of Local Notifications is from an MAF perspective not different from Push Notifications
First we need to create an eventListener that specifically listens for Local Notifications.
This class must implement oracle.adfmf.framework.event.EventListener.
In this class we must use the onMessage() method, which will fire when a notification is received.
After creating this Listener class it must be added as an eventSource in the start Method of the application Lifecycle Listener.
In this way, each time the app starts, we make sure the app is actually Listening to the local Notification event.
With all of this code in place, the app is ready to listen for and respond to local notification.
Creating local Notifications from Java
Creating a new Notification is pretty much straightforward. In this example we use a button to create a local Notification.
To work with Local Notifications using Java, the frameworks' utility class oracle.adfmf.framework.api.AdfmfContainerUtilities contains several methods to help you. The first one is addLocalNotification(). This method can be used to create a local notification. It needs an MafNativeLocalNotificationOptions Object.
The MafNativeLocalNotificationOptions Object contains several properties that can be used for notifications.
So for creating a local Notification we first need to create a new MafNativeLocalNotificationOptions object, called options in the code below. Next we set the values for all, or many, of the properties such as alertTitle, alert, notifationDate, badge and maybe even sound and vibration. Also, if the notification needs a payload we need to set this payload. Once these values are properly set we can add a new notification to the app by calling addLocalNotification(). The call to this method returns a String containing the notificationId.
Once this notification is added, it will show up at the given moment; in this case the date that is set with options.setDate(). It will show the Notification with the corresponding message; in this case "Did you Forget Something ?" as set by setAlert();
Cancelling a Notification
Sometimes, a notification is set as a reminder for some action. As in the previous example, "Did you forget something", the user is reminded to do something. There are situations where the user already did what you reminded him to do. In that case we don't want to show the notification.
For that purpose we can use the cancelLocalNotification() method in the AdfmfContainerUtilities class. To cancel the notification we must provide the notification ID.
Scheduling a Repeating Notification
If we want to schedule a notification to fire every time during a given interval we can use the setRepeat() on the MafNativeLocalNotificationOptions. An example of this could be that you want to remind the user to open his app every day to check for changes. So if we want a notification that is scheduled to fire every Day we simply need to call setRepeat() with interval Daily.
Just for testing and for the purpose of the demo I like to work with a Minutely interval. This makes not a lot of sense, but for testing, it is a good interval, at least compared to yearly.... The available options are displayed below:
Cancelling a Repeating Notification: A Solution for a Limitation
Now lets assume we have a clever user who by now knows that we what him to check his app every day. So here is the situations where the user already did what you reminded him to do. In that case we don't want to show the notification.
For that purpose we must also use the cancelLocalNotification() method in the AdfmfContainerUtilities class. Cancelling a notification means that the notification is COMPLETELY cancelled even if it was scheduled to fire every DAY. Once cancelled, it will no longer notify, not even the next day. So in order to make this really work, cancel today and notify tomorrow, we must create a new local notification, exactly like the one that was just cancelled with interval DAILY.
Just for testing purposes I added an application preference that I can use to indicate whether or not I really want to recreate the local notification.
Look at the logfile below and see what happens. First, the notification is created (1), then it is cancelled (2), and immediately recreated !
NOTE (1): The above limitation is not a limitation of Oracle MAF. This is simply how local notifications work on the Operating Systems. Although I am not 100% sure that the solution of re-creating the notification is the most optimal, for now it really seems to be the only way to make this work.
Resources
MAF Developer Guide Chapter 24
The sources of this app are available here.
These notifications originate within the MAF application and are received by the same application. They are delivered to the end user through standard mechanisms supported by the mobile device platform (for example, banner, sound) and can work when the application is either in the foreground, background or not running at all.
I this post I show you an example of how to work with Local Notifications from Java. I use a simple MAF app. I will not explain how to build this app, but the source can be downloaded here. It is mainly derived from the "LocalNotificationDemo" public sample app.
Introducing Local Notifications
As with many framework features, MAF supports three ways to set Local Notifications. First you can use the device features datacontrol. To support declarative use of Local Notifications, the DeviceFeatures data control includes the addLocalNotification and cancelLocalNotification methods, which enable MAF applications to leverage a device's interface for managing notifications so end users can schedule or cancel local notifications.
Second you have the option to set Local Notifications from JavaScript. MAF allows you to manage local notifications using JavaScript APIs in the adf.mf.api.localnotification namespace. The methods add() and cancel() are available. More info on this is available from the developer guide (see resources at the end of this post).
Finally you can set Local Notifications from Java code, which is what I will explain in the remaining part of this post.
Set up the Listening Part
Because the Listening part is the same for all methods mentioned above I will start to explain this before going into detail for setting Local Notifications from Java code.
The concept of Local Notifications is from an MAF perspective not different from Push Notifications
First we need to create an eventListener that specifically listens for Local Notifications.
This class must implement oracle.adfmf.framework.event.EventListener.
In this class we must use the onMessage() method, which will fire when a notification is received.
public class MyLocalNotificationListener implements EventListener { public MyLocalNotificationListener() { } public void onMessage(Event event) { // work with the notification event // Here we can get the application state (for wich we can use a util method) and the payload String appState = stringifyAppState(event.getApplicationState()); String payload = event.getPayload(); // Now do whatever we want, for instance call a feature AdfmfContainerUtilities.gotoFeature("com.blogspot.lucbors.lnb.NotificationShower"); } private String stringifyAppState(int appState) { switch(appState) { case Event.APPLICATION_STATE_FOREGROUND: return "FOREGROUND"; case Event.APPLICATION_STATE_BACKGROUND: return "BACKGROUND"; case Event.APPLICATION_STATE_NOT_RUNNING: return "NOT RUNNING"; } return "UNKNOWN"; }
After creating this Listener class it must be added as an eventSource in the start Method of the application Lifecycle Listener.
In this way, each time the app starts, we make sure the app is actually Listening to the local Notification event.
public void start() { // Listen for local notifications EventSource evtSource = EventSourceFactory.getEventSource(EventSourceFactory.NATIVE_LOCAL_NOTIFICATION_EVENT_SOURCE_NAME); evtSource.addListener(new MyLocalNotificationListener()); }
With all of this code in place, the app is ready to listen for and respond to local notification.
Creating local Notifications from Java
Creating a new Notification is pretty much straightforward. In this example we use a button to create a local Notification.
To work with Local Notifications using Java, the frameworks' utility class oracle.adfmf.framework.api.AdfmfContainerUtilities contains several methods to help you. The first one is addLocalNotification(). This method can be used to create a local notification. It needs an MafNativeLocalNotificationOptions Object.
The MafNativeLocalNotificationOptions Object contains several properties that can be used for notifications.
protected String title; protected String alert; protected LocalDateTime date; protected RepeatInterval repeat; protected int badge; protected String sound; protected String vibration; protected HashMap <String> payload;
So for creating a local Notification we first need to create a new MafNativeLocalNotificationOptions object, called options in the code below. Next we set the values for all, or many, of the properties such as alertTitle, alert, notifationDate, badge and maybe even sound and vibration. Also, if the notification needs a payload we need to set this payload. Once these values are properly set we can add a new notification to the app by calling addLocalNotification(). The call to this method returns a String containing the notificationId.
public void addNotificationForAction(ActionEvent actionEvent) { String notificationDate = "now"; try { // Set the notification options MafNativeLocalNotificationOptions options = new MafNativeLocalNotificationOptions(); options.setTitle("Just Some Reminder"); options.setAlert("Did you Forget Something ?"); if (date != null) { date.setSeconds(0); // Clear the seconds component to fire on the minute LocalDateTime l = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()) , ZoneOffset.UTC); options.setDate(l); DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); notificationDate = dateFormat.format(date); } options.setBadge(-1); if (sound) { options.setSound(MafNativeLocalNotificationOptions.SOUND_DEFAULT_SYSTEM); } if (vibration) { options.setVibration(MafNativeLocalNotificationOptions.VIBRATION_DEFAULT_SYSTEM); } // Set 3 values in the JSON payload HashMap<String Object> payload = new HashMap<String Object>(); payload.put("key1", 1); payload.put("key2", "hello"); payload.put("key3", true); options.setPayload(payload); // Add the notification String notificationID = AdfmfContainerUtilities.addLocalNotification(options); System.out.println("++++ Notification added successfully for " + notificationDate); System.out.println("++++ Notification ID is " + notificationID); } catch(Exception e) { System.out.println("++++ There was a problem adding notification: " + e.getMessage()); e.printStackTrace(); } }
Once this notification is added, it will show up at the given moment; in this case the date that is set with options.setDate(). It will show the Notification with the corresponding message; in this case "Did you Forget Something ?" as set by setAlert();
Cancelling a Notification
Sometimes, a notification is set as a reminder for some action. As in the previous example, "Did you forget something", the user is reminded to do something. There are situations where the user already did what you reminded him to do. In that case we don't want to show the notification.
For that purpose we can use the cancelLocalNotification() method in the AdfmfContainerUtilities class. To cancel the notification we must provide the notification ID.
public void cancelLocalNotification(ActionEvent actionEvent) { try { // We use the notificationId that was set when the notification was added //setNotificationId( AdfmfContainerUtilities.addLocalNotification(options)); String cancelledNotificationId = AdfmfContainerUtilities. cancelLocalNotification(notificationId); System.out.println("Notification successfully canceled"); } catch(AdfException e) { System.err.println("There was a problem cancelling notification"); } }
Scheduling a Repeating Notification
If we want to schedule a notification to fire every time during a given interval we can use the setRepeat() on the MafNativeLocalNotificationOptions. An example of this could be that you want to remind the user to open his app every day to check for changes. So if we want a notification that is scheduled to fire every Day we simply need to call setRepeat() with interval Daily.
options.setRepeat(MafNativeLocalNotificationOptions.RepeatInterval.DAILY);
Just for testing and for the purpose of the demo I like to work with a Minutely interval. This makes not a lot of sense, but for testing, it is a good interval, at least compared to yearly.... The available options are displayed below:
Cancelling a Repeating Notification: A Solution for a Limitation
Now lets assume we have a clever user who by now knows that we what him to check his app every day. So here is the situations where the user already did what you reminded him to do. In that case we don't want to show the notification.
For that purpose we must also use the cancelLocalNotification() method in the AdfmfContainerUtilities class. Cancelling a notification means that the notification is COMPLETELY cancelled even if it was scheduled to fire every DAY. Once cancelled, it will no longer notify, not even the next day. So in order to make this really work, cancel today and notify tomorrow, we must create a new local notification, exactly like the one that was just cancelled with interval DAILY.
Just for testing purposes I added an application preference that I can use to indicate whether or not I really want to recreate the local notification.
public void cancelLocalNotification(ActionEvent actionEvent) { try { // We use the notificationId that was set when the notification was added //setNotificationId( AdfmfContainerUtilities.addLocalNotification(options)); String cancelledNotificationId = AdfmfContainerUtilities. cancelLocalNotification(notificationId); System.out.println("Notification successfully canceled"); Boolean recreate = (Boolean)AdfmfJavaUtilities.evaluateELExpression( "#{preferenceScope.application.ReCreateNotificationAfterCancel.ReCreate}"); // if recreate preference is true if (recreate.booleanValue()){ addNotification(); } } catch(AdfException e) { System.err.println("There was a problem cancelling notification"); } }
Look at the logfile below and see what happens. First, the notification is created (1), then it is cancelled (2), and immediately recreated !
NOTE (1): The above limitation is not a limitation of Oracle MAF. This is simply how local notifications work on the Operating Systems. Although I am not 100% sure that the solution of re-creating the notification is the most optimal, for now it really seems to be the only way to make this work.
Resources
MAF Developer Guide Chapter 24
The sources of this app are available here.
Comments