The Push Notes App is a Gluon code sample. Refer to the Gluon website for a full list of Gluon code samples.
In this tutorial, we’ll explain how to modify the Notes application to support push notifications and deploy it on Android and iOS devices. Before you start, be sure that you have checked the list of prerequisites, and you have installed the Gluon plugin for your IDE. Otherwise follow these instructions.
Note: This tutorial will use the plugin for NetBeans, but it works as well on IntelliJ and Eclipse.
Code: The code for this project can be found in the samples repository at
GitHub. The sample is located under the directory pushnotes
. The reader can clone this repository or create the entire
project from scratch, based on the following steps.
Creating the project
This project can be created from scratch using the Gluon plugin on your favourite IDE. But since this is a follow up of
the Notes app, we’ll clone the original Notes sample instead and modify it to add new features. We’ll refactor the main package to com.gluonhq.pushnotes
and the application class to PushNotes
. Make sure to do the necessary adjustments in the FXML (fx:controller
), build.gradle
,
AndroidManifest.xml
and Default-info.plist
files.
Modifying the project
Let’s start modifying the default project to create our PushNotes application, based on the Notes sample.
The model package
The model package contains the Note
, Model
and Settings
classes, exactly the same as in the Notes sample.
The service
In the original Notes sample, we created a service that used Gluon CloudLink to persist the notes we created and/or edited locally on the device. We’ll now modify that same service by persisting the data in the cloud.
When creating the DataClient
object, we’ll use OperationMode.CLOUD_FIRST
to indicate that data will be directly
stored into and retrieved from Gluon CloudLink. Using a DataProvider
as an entry point to retrieve a GluonObservableList
, we need to supply a proper ListDataReader
, a valid entity with the ability to read a list of objects. For that, the DataClient
instance already has one method: createListDataReader()
. All it needs is an identifier (NOTES
), and the object class to be read (Note.class
).
You can read more about the Gluon CloudLink Data Storage service here.
public class Service {
private static final String NOTES = "notes-v4";
private static final String NOTES_SETTINGS = "notes-settings-v4";
private final ListProperty<Note> notes = new SimpleListProperty<>(FXCollections.observableArrayList());
private final ObjectProperty<Settings> settings = new SimpleObjectProperty<>(new Settings());
private DataClient dataClient;
@PostConstruct
public void postConstruct() {
dataClient = DataClientBuilder.create()
.operationMode(OperationMode.CLOUD_FIRST)
.build();
}
public void retrieveNotes() {
GluonObservableList<Note> gluonNotes = DataProvider.<Note>retrieveList(
dataClient.createListDataReader(NOTES, Note.class,
SyncFlag.LIST_WRITE_THROUGH, SyncFlag.LIST_READ_THROUGH,
SyncFlag.OBJECT_WRITE_THROUGH, SyncFlag.OBJECT_READ_THROUGH));
gluonNotes.stateProperty().addListener((obs, ov, nv) -> {
if (ConnectState.SUCCEEDED.equals(nv)) {
notes.set(gluonNotes);
retrieveSettings();
}
});
}
...
}
Registering the app
The DataClient
uses a key and a secret token that are specific for the application. Those tokens are used for signing
the requests that are made to Gluon CloudLink. To obtain a key and secret, you need a valid subscription to Gluon CloudLink. You can get it here (there is also a 30-day free trial). Sign up and get a valid account on Gluon CloudLink and a link to access the Gluon Dashboard.
Open the Dashboard in your browser, and sign in using the Gluon account credentials provided to create the account.
Go to the App Management link, and you will
find a pair of key/secret tokens. Click on the download button to download the file gluoncloudlink_config.json
, and then store it under your project src/main/resources/
folder.
The content of the file is a JSON object with the key and secret that will grant access to Gluon CloudLink:
{
"gluonCredentials": {
"applicationKey" : "f88XXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"applicationSecret": "7fbXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}
}
Running the app
After updating the project, let’s run it on desktop to test that everything is in place.
We can also create one note:
and change the settings:
and we should see the results on the main view:
If we close the app and open it again, the list of notes and the settings should be the same, as everything is persisted in the cloud, thanks to the Gluon CloudLink.
Gluon Dashboard
To track all the changes that happen in the cloud application you can run the Gluon Dashboard web application in your browser again. Sign in with your credentials and go to the Data Management link, you will be able to see the actual content of the settings object (Object tab) and the notes list (List tab):
At anytime you can delete any entry, and this will be propagated to the client app.
Push Notifications
We can add push notifications to our app in two simple steps: Adding the required Charm Down plugins and adding a PushClient
instance.
Required Plugins
Right click on your project root, and select Gluon Mobile Settings
.
On the left list, find and select Push Notifications, and click on the >
button:
Also add the Device plugin:
Notice that the list of plugins will be updated accordingly on your build.gradle
file:
jfxmobile {
downConfig {
version = '3.8.0'
// Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
plugins 'device', 'display', 'lifecycle', 'push-notifications', 'runtime-args', 'statusbar', 'storage'
}
...
}
Reload the project, so the new dependencies are resolved.
The PushClient
On the application class, add an instance of PushClient and call the enable
method, passing in an authorizedEntity
.
The value for the authorizedEntity
parameter is the Sender ID
of your Google Cloud Messaging or Firebase Cloud
Messaging application. Follow this guide to get the
authorizedEntity
key.
Note: this value is only required for Android apps. iOS apps don’t need any specific configuration for the PushClient.
public class PushNotes extends MobileApplication {
@Override
public void postInit(Scene scene) {
...
PushClient pushClient = new PushClient();
pushClient.enable("43XXXXXXXXXXX");
}
}
Android
Modify the AndroidManifest file
According to the documentation for the Push Notifications plugin, edit and modify the AndroidManifest.xml file to include the required changes for this plugin:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gluonhq.pushnotes" android:versionCode="1" android:versionName="1.0">
<supports-screens android:xlargeScreens="true"/>
<permission android:name="com.gluonhq.pushnotes.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.gluonhq.pushnotes.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="21"/>
<application android:label="pushnotes" android:name="android.support.multidex.MultiDexApplication" android:icon="@mipmap/ic_launcher">
<meta-data android:name="com.google.android.gms.version" android:value="9452000"/>
<activity android:name="javafxports.android.FXActivity"
android:label="pushnotes"
android:launchMode="singleTop"
android:configChanges="orientation|screenSize">
<meta-data android:name="main.class" android:value="com.gluonhq.pushnotes.PushNotes"/>
<meta-data android:name="debug.port" android:value="0"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.gluonhq.pushnotes" />
</intent-filter>
</receiver>
<service
android:name="com.gluonhq.impl.charm.down.plugins.android.PushGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service
android:name="com.gluonhq.impl.charm.down.plugins.android.PushInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<service
android:name="com.gluonhq.impl.charm.down.plugins.android.RegistrationIntentService"
android:exported="false" >
</service>
<activity android:name="com.gluonhq.impl.charm.down.plugins.android.PushNotificationActivity"
android:parentActivityName="javafxports.android.FXActivity">
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="javafxports.android.FXActivity"/>
</activity>
</application>
</manifest>
Deploy to Android
Connect your Android device and run ./gradlew clean androidInstall
. Opening the app will already show the note with the desktop client:
Sending a Push Notification
Within the Gluon Dashboard web application, select the Push Notifications link and open the Configuration tab. Paste the Server Key from your Google Cloud Messaging or Firebase Cloud Messaging application:
Back to the Push Notifications tab you can create a new notification, pressing the +
button. Provide a title and a body and
click Accept.
Immediately you will hear the notification on your Android phone.
Clicking on it will open the application if it was closed, or put it on the foreground if it was in the background.
iOS
Certificates
Follow this step-by-step guide to get a p12 certificate for the dashboard and the provisioning profile for your app.
Signing the app
At the Apple Developer portal create and download the provisioning profile for your application.
Edit the build.gradle file to configure the project to use this provisioning profile. Also include the apsEnvironment
clause, with either 'development'
or 'production'
, depending on the type of certificate you are using.
jfxmobile {
ios {
...
iosSignIdentity = 'iPhone Developer: ...'
iosProvisioningProfile = 'Push Notes Provisioning Profile'
apsEnvironment = 'development'
}
}
Connect your iOS device and run ./gradlew clean launchIOSDevice
. A confirmation dialog will pop up, asking if you want
to allow notifications. Accept it to allow push notifications to be sent to your device for this application.
Gluon Dashboard
Create the p12 certificate and upload it to CloudLink using the Dashboard web application. Please make sure to upload the correct certificate type for the correct environment.
Processing push notifications
When the push notification is delivered to the device, a notification shows up. When clicking on it, the application is opened if it wasn’t running, or it is resumed if it was running on the background.
You can listen to that moment, and perform some action based on the payload of the notification using the Runtime Args Service:
@Override
public void postInit(Scene scene) {
...
Services.get(RuntimeArgsService.class).ifPresent(ras -> {
ras.addListener(RuntimeArgsService.LAUNCH_PUSH_NOTIFICATION_KEY, f -> {
System.out.println("Received a push notification with contents: " + f);
});
});
...
}
If the push notification sent from the Dashboard is marked as silent, there won’t be a visible notification, but the listener will be called and it will be able to process the payload.
Conclusion
During this tutorial we have accomplished several tasks after updating the existing Notes sample:
-
We have modified the Notes sample to add cloud persistence with
DataClient
andGluonObservableList
. And by using the Dashboard application we’ve been able to track the changes in those persisted lists and objects. -
We have added new plugins to the project: Device and Push Notifications.
-
We have registered the app in Google Cloud Messaging and/or the Apple Developer center, and retrieved the required keys and/or certificates.
-
We have enabled push notifications on Android and iOS, and by using the Dashboard web application we have tested them on both platforms.
If you have made it this far, congratulations, we hope this sample and the documentation was helpful to you! In case you have any questions, your first stop should be the Gluon support page, where you can access the latest documentation and the Gluon knowledge base. Gluon also recommends the community to support each other over at the Gluon StackOverflow page. Finally, Gluon offers commercial support as well, to kick start your projects.