Skip to main content

Hybrid Mobile Application

This section explains how to build one hybrid application based on a Simplicité project:

  • Available on Play store and Apple store
  • Embed the responsive website and support HTML5/CSS3
  • Allows device and desktop to receive notifications
  • and server back-end to post messages (to users, or groups or all users)

Cordova

Prerequisites

Environment variables

  • JAVA_HOME : JVM root (ex C:\dev\java\jdk1.8)
  • ANDROID_HOME and ANDROID_SDK_ROOT : root of your android SDK (ex C:\dev\android\sdk)
  • GRADLE_USER_HOME : change the gradle home repository without special characters in path (ex C:\dev\.gradle)
  • Add to PATH
    • the studio gradle (ex C:\dev\android\studio\gradle\gradle-4.6\bin)
    • the JVM bin directory (ex C:\dev\java\jdk1.8\bin)

Install cordova CLI

npm install -g cordova`
cordova --version

Create your application

cordova create myproject com.simplicite.mobile.myproject MyProjectName
cd myproject

Add platforms and plugins with CLI

cordova platform add android
cordova plugin add cordova-plugin-whitelist
cordova plugin add cordova-plugin-inappbrowser
cordova plugin add cordova-plugin-network-information
cordova plugin add cordova-plugin-dialogs
...

Androïd test

Create/launch one emulator in Android Studio then:

cordova build android
cordova emulate android

Starts on your device in debug mode:

  • see
  • see
cordova run android

In Android Studio:

  • You will have to validate the license terms before using the tools
  • Create one ADV (virtual device) before using cordova emulate android
  • After cordova generation, open the project /platforms/android to build/test the app

Integrate the hybrid app

Open your project directory and customize your application:

  • www/img/logo.png is used on the default splash screen
  • all res/icon/android and res/icon/ios with your logos
  • change the default www/js/index.js
    • Init firebase plugin to register / receive notifications on each device
    • Launch the webapp into a inAppBrowser : the simplest way to wrap the site into a browser (but with some limitations)

Script www/js/index.js

(function() {

var url = 'https://myproject.myserver.simplicite.io';
var fireBaseToken, win, winReady;

// Call the UI firebase handler
function exec(d) {
d = typeof(d)=="string" ? d : JSON.stringify(d);
winReady && win.executeScript({ code: 'window.$ui.firebase(' + d + ');' });
}

// Notify server with firebase token after login
function syncFirebaseToken(token) {
token = token || fireBaseToken;
if (token) {
fireBaseToken = token;
exec({ token:token });
}
}

function error(e) { console.error(e); }

// Firebase events
function firebase() {
// Notification : cordova-plugin-firebase
var pfb = window.FirebasePlugin;
if (pfb) {
console.log("[FirebasePlugin] init");
//pfb.grantPermission();
pfb.getToken(syncFirebaseToken, error);
pfb.onTokenRefresh(syncFirebaseToken, error);
pfb.onNotificationOpen(function(m) {
console.log("[FirebasePlugin] onNotificationOpen " + JSON.stringify(m));
exec(m);
}, error);
}
}

// Load Simplicite URL
function open() {
// In-app browser
win = cordova.InAppBrowser.open(url + "?inapp=true", '_blank', 'location=no');
win.addEventListener('loadstop', function() {
winReady = true;
syncFirebaseToken();
});
//win.addEventListener('exit', function() {});
}

// Cordova loaded
function init() {
var parentElement = document.getElementById('deviceready');
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
}
function ready() {
init();
firebase();
open();
}
document.addEventListener("deviceready", ready, false);
})();

Application icons

  • Import your icons into res/icon folders
  • Change config.xml to bind all sizes as follow:
    <platform name="android">
...
<icon density="ldpi" src="res/icon/android/icon-36-ldpi.png" />
<icon density="mdpi" src="res/icon/android/icon-48-mdpi.png" />
<icon density="hdpi" src="res/icon/android/icon-72-hdpi.png" />
<icon density="xhdpi" src="res/icon/android/icon-96-xhdpi.png" />
</platform>
<platform name="ios">
...
<icon height="114" src="res/icon/ios/icon-57-2x.png" width="114" />
<icon height="57" src="res/icon/ios/icon-57.png" width="57" />
<icon height="144" src="res/icon/ios/icon-72-2x.png" width="144" />
<icon height="72" src="res/icon/ios/icon-72.png" width="72" />
</platform>

Splash screen

  • Install the plugin splash screen:
cordova plugin add cordova-plugin-splashscreen
  • Put all your image in project's resources, example /res/screen/android/screen-hdpi-landscape.png
  • Add to config.xml the size mapping
<platform name="android">
...
<splash src="res/screen/android/screen-hdpi-landscape.png" density="land-hdpi"/>
...
</platform>

Firebase configuration

Firebase is used to manage Cloud messaging and notifications.

The platform will use several system parameters:

  • FIREBASE : to activate the service on platform and UI
  • FIREBASE_PRIVATE_KEY : private setup to init the service on server side
  • FIREBASE_TOKENS : used to store each user devices (desktop, mobile, tablet...)
  • FIREBASE_CONFIG : public configuration on Web client-side
  • FIREBASE_LIBS : public firebase libs to load on client-side
  • FIREBASE_VAPID_KEY : public key for firebase authentication

Register your application on Firebase

  1. Create your Firebase account
  2. Access to the console to add your project, ex SimpliciteMobileMyProject

Add to project the application for Androïd

  • with your cordova package name (ex com.simplicite.mobile.myproject)
  • generate and download the google-services.json in your local project root, it is required to compile the firebase plugin
  • and copy google-services.json into platforms/android/app in case of build error

Add the firebase plugin

Notification

cordova plugin add cordova-plugin-firebase
cordova run android

In case of build error on android platform (invalid google play version), uninstall this plugin and use this compatible fork: cordova-plugin-firebasex

Send a message with the console

  • Use the google console to access the Cloud Messaging section of your project
  • Compose a message
  • Verify your device

Back-end integration

Set system parameter FIREBASE = yes to activate the service. On UI $ui.firebase wrap all Firebase message:

  • to register user and device on server-side (see FIREBASE_TOKENS on each user)
  • to send a notification to users (unique, groups or all)

on Server-side service, see GoogleFireBaseTools:

  • you must generate first your Service Account Key on console
  • then place your strongly private credentials in the parameter FIREBASE_PRIVATE_KEY on server-side
{
"type": "service_account",
"project_id": "simplicite-app",
"private_key_id": "e82...",
"private_key": "-----BEGIN PRIVATE KEY----- xxxx -----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-f5n4s@simplicite-app.iam.gserviceaccount.com",
"client_id": "1234...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-f5n4s%40simplicite-app.iam.gserviceaccount.com"
}

Front-end integration (desktop)

To receive message on webapp, the browser needs 2 parameters:

  1. Add a public system param FIREBASE_LIBS

    [
    "https://www.gstatic.com/firebasejs/7.20.0/firebase-app.js",
    "https://www.gstatic.com/firebasejs/7.20.0/firebase-messaging.js"
    ]
  2. Add a public system param FIREBASE_CONFIG to init firebase on client-side:

    • see
    • or access to console / Project / Setup / Add Firebase to your Web application
    {
    "apiKey": "AIzaSyB...",
    "authDomain": "simplicite-app.firebaseapp.com",
    "databaseURL": "https://simplicite-app.firebaseio.com",
    "projectId": "simplicite-app",
    "storageBucket": "simplicite-app.appspot.com",
    "messagingSenderId": "123...",
    "appId": "1:1234...",
    "measurementId": "G-XXX..."
    }
  3. Add a public system param FIREBASE_VAPID_KEY to authent client

    Get the public VAPID key from key-pair on Firebase console / Configuration web:

    BIDDmZgk5QSFd7Bf1sf2yfUrfi...

note firebase is not loaded in webapp:

  • If FIREBASE_CONFIG is not set on platform
  • If webapp is embedded into mobile inAppBrowser: cordova includes the firebase plugin and events outside the site

Unit test

JSON message:

"data":{
"title": "hello",
"body": "world",
"priority": "high | normal | low",
"icon": "notification_icon"
}

To send one notification to a device:

curl --header "Authorization: key=<cloud messaging server key>" \
--header "Content-type: application/json" \
-d '{"to":"<device token>", "data":{"title":"hello","body":"world","icon":"notification_icon"}}' \
https://fcm.googleapis.com/fcm/send
  • Get the server key on your Firebase console / Project Setup / Cloud Messaging / Server key Token (use the long one, the short key is deprecated)
  • Get the device token stored in user's FIREBASE_TOKENS (or logged in browser console)

Notification icons

  • iOS does not support customization and use the default app icon
  • Android supports icon resources referenced in notification:
  1. Generate your mono-color/transparent icons:
  2. Import them into your project res/icon/android
  3. Add resources in config.xml to copy them in drawable as notification_icon
    <platform name="android">
...
<resource-file src="res/icon/android/drawable-mdpi/notification_icon.png" target="app/src/main/res/drawable-mdpi/notification_icon.png" />
<resource-file src="res/icon/android/drawable-hdpi/notification_icon.png" target="app/src/main/res/drawable-hdpi/notification_icon.png" />
<resource-file src="res/icon/android/drawable-xhdpi/notification_icon.png" target="app/src/main/res/drawable-xhdpi/notification_icon.png" />
<resource-file src="res/icon/android/drawable-xxhdpi/notification_icon.png" target="app/src/main/res/drawable-xxhdpi/notification_icon.png" />
<resource-file src="res/icon/android/drawable-xxxhdpi/notification_icon.png" target="app/src/main/res/drawable-xxxhdpi/notification_icon.png" />
</platform>

see:

Deploy on Google Play Store

Assuming your application is working on debug mode on your mobile device, you can push your signed APK on the play store.

Build a release APK

cordova build --release android

The unsigned APK is generated in your android directory myproject/platforms/android/app/build/outputs/apk/release/app-release-unsigned.apk

Sign your APK file

Create a keystore with your company information:

cordova build android --release -- --keystore="path/to/keystore" --storePassword=xxxx --alias=key0 --password=xxxx

The signed APK is generated in your android directory myproject/platforms/android/app/build/outputs/apk/release/app-release.apk

Upload the APK with the play-store console

You will have to change the version each time you deliver an new APK:

  • in root files config.xml and package.json
  • rebuild the release

See Google documentation

Process is quite long at the very first time:

  • Sign all confidentiality, brief, class PEGI 3, tax free...
  • Create the application, upload and validate your APK
  • Create a testing group
  • Publish in test mode: not visible on public store but here: https://play.google.com/apps/testing/com.simplicite.mobile.myproject
  • Promote to production when ready to use: https://play.google.com/store/apps/details?id=com.simplicite.mobile.myproject

Congrats if you are still alive at this stage!

Deploy on Apple Store

Install the iOS platform

You will have to do the same with iOS platform on your Mac. It is not possible to build the app on PC/Windows. iOS app requires Xcode to compile swift code and cordova plugins.

See

  • Create your apple ID
  • Download Xcode 10
  • configure xcode-select to target the Xcode installation
  • install CLI to compile and deploy
  • then rebuild your cordova app with the iOS platform
sudo xcode-select --install
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
npm i -g xcode
npm i -g ios-deploy
cordova platform add ios
cordova build ios

If the build is successful, launch all emulators (iPhone, iPad) to test the app with Xcode:

  • cordova can not launch the app directly, open the project in /platforms/ios
  • on top select your emulator and starts the app
  • at bottom open the log console filtered on your app name

iOS icons

The application needs many icons to target all iOS versions.

  • Open the project platforms/ios/myproject.xcworkspace in Xcode
  • Select the icon overview /Resources/Images.xcassets

  • Create all icons in res/icon/ios directory
  • Add icons in your config.xml:
    <platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
<icon height="180" src="res/icon/ios/icon-60-3x.png" width="180" />
<icon height="120" src="res/icon/ios/icon-60-2x.png" width="120" />
<icon height="60" src="res/icon/ios/icon-60.png" width="60" />
<icon height="152" src="res/icon/ios/icon-76-2x.png" width="152" />
<icon height="76" src="res/icon/ios/icon-76.png" width="76" />
<icon height="80" src="res/icon/ios/icon-40-2x.png" width="80" />
<icon height="40" src="res/icon/ios/icon-40.png" width="40" />
<icon height="114" src="res/icon/ios/icon-57-2x.png" width="114" />
<icon height="57" src="res/icon/ios/icon-57.png" width="57" />
<icon height="144" src="res/icon/ios/icon-72-2x.png" width="144" />
<icon height="72" src="res/icon/ios/icon-72.png" width="72" />
<icon height="87" src="res/icon/ios/icon-small-3x.png" width="87" />
<icon height="58" src="res/icon/ios/icon-small-2x.png" width="58" />
<icon height="29" src="res/icon/ios/icon-small.png" width="29" />
<icon height="100" src="res/icon/ios/icon-50-2x.png" width="100" />
<icon height="50" src="res/icon/ios/icon-50.png" width="50" />
<icon height="167" src="res/icon/ios/icon-167.png" width="167" />
</platform>

Setup firebase for iOS

  • Create the App ID

    • Description = Simplicite My Project
    • Explicit App ID = com.simplicite.mobile.myproject
    • App services = add Push notifications
  • Generate the CSR file: Certificate Signing Request

    • On your mac open the Keychain access
    • Menu Certificate assistant > Request a certificate from a certificate authority
    • Enter your email and full name, store the file on disk
  • Prepare the APN (Apple Push Notification) certificate

    • Edit the App ID to create the notification certificates
    • In Push notification section / developer
    • Upload the CSR file
    • Download the generated certificate aps_development.cer
    • Add it to your session certificates in Keychain access
    • With keychain, open the certificate Apple Development Push Services
    • And export your private key into a p12 file
  • Configure firebase

    • In the firebase console, open the project setup
    • In Cloud messaging section upload the certificate APNs

See all steps here:

Create the Provisioning Profile

To test your app before the final deployment in App Store, you have to sign the app thru a physical iOS device (so buy one iPhone or iPad!).

  • Create a development key and Team with the CSR file

  • On the console create a device item with its serial number

    • connect the device to your mac thru USB link
    • use iTunes to open the device infos to get the serial number
  • Then create a profile to associate the App ID with the device

  • Download the profile into Xcode

    • Menu Preferences / Account / Settings to import the profile
    • Open the application properties and select the Development Team to sign the App
    • Launch the app with your real device
    • During compilation enter your certificate password
    • Enjoy when the App brings to life on device!

Deploy on the Apple store

The last step is to create the Store listing:

  • login to
  • Create the App with Plus button
  • Set the title, sub-title and description, privacy-policy URL, etc.
  • Upload screenshots for iPhone and iPad
  • Push the build from Xcode Menu Product/Archive to build and download the signed ipafile
  • Give a login/password to allow Apple to make internal verifications
  • Submit to verify the App, the process can be very long (form 1 to 10 days)

See

Known limitations with inAppBrowser

  • Google OAuth2 doesn't work into the inAppBrowser for security reason (only thru native browsers Chrome or Safari)
  • W3C navigator.mediaDevices is not yet supported by inAppBrowser (missing some CAMERA permissions)