IBM / Ionic-MFP-App

This repository contains instructions to develop a secure, enterprise-grade Ionic/Cordova based hybrid mobile app that connects to CouchDB/Cloudant and ObjectStorage via IBM Mobile Foundation service.
https://developer.ibm.com/patterns/develop-hybrid-mobile-app-with-cloud-native-back-end/
Apache License 2.0
15 stars 25 forks source link
cloudant-database cloudant-nosql-database ibm-cloud ibm-developer-technology-cloud ibm-mobilefirst ibmcode imgcache ionic ionic2 ionic3 mfp object-storage

Develop Enterprise-grade Hybrid Mobile App with Cloud-native Backend

When developing your enterprise mobile app that needs centralized hosting of data, use of cloud-native services such as Cloudant No-SQL Database for storing textual data and Object Storage service for storing image/video/audio data, allows you to quickly go from idea-conception to reality. The Mobile Foundation service available from IBM Cloud provides a scalable mobile access gateway for securely accessing those backend services, and it provides other essential mobile backend capabilities such as push notifications, app lifecycle management and app analytics.

This code pattern gives you step by step instructions for developing an Ionic/Cordova based hybrid mobile app that securely connects to Cloudant and Object Storage services via IBM MobileFoundation (aka MFP) service.

When you have completed this pattern, you will understand:

Flow

Architecture diagram
  1. User launches the mobile app, enters his/her credentials on the login screen and clicks Login.
  2. Mobile app sends the user credentials to MFP server for validation.
  3. MFP server invokes the security adapter logic to validate user credentials and returns an appropriate response to the mobile app. For the sake of this demo, we will use a simple security adapter that returns success when password equals username.
  4. If user authentication succeeds, mobile app proceeds to show the home page. As part of this, it makes a call to MFP adapter to fetch the data from Cloudant NoSQL database.
  5. MFP adapter fetches the data from Cloudant and returns it to the mobile app. The data fetched from Cloudant will have references to the images stored in Cloud Object Storage.
  6. Mobile app makes a call to MFP adapter to get the Authorization token for interacting with Cloud Object Storage service.
  7. MFP adapter makes a call to Cloud Object Storage service's token manager endpoint to get the Authorization token and returns it to the mobile app.
  8. Mobile app initializes image-caching plugin and asks it to use an HTTP header of Authorization=<value returned from MFP adapter> while fetching images. Mobile app displays the data obtained from MFP adapter as a list of items. The image caching plugin running on the mobile app downloads and caches images from Cloud Object Storage.
  9. User clicks on one of the list item to see more details. A detail page is shown consisting of image and geo-location marked inside Google Maps.
  10. Back in the home page, user clicks on + button to report a new civic problem. A new page is shown where user can enter a description for the new civic problem as well as capture image and geo-location of the problem spot. User clicks on Submit button.
  11. Mobile app uploads the textual data to Cloudant NoSQL DB via MFP Adapter.
  12. Mobile app creates a thumbnail image by resizing the captured image and uploads both the captured image and thumbnail to Cloud Object Storage.
  13. Other users who click on refresh button on the home page (and those who log in afresh) are shown the updated list of problem reports.

Included Components

Featured Technologies

Watch the Video

Steps

  1. Setup Ionic and MFP CLI
  2. Create Cloudant database and populate it with sample data
  3. Create IBM Cloud Object Storage service and populate it with sample data
  4. Create Mobile Foundation service and configure MFP CLI
  5. Download source repo and customize
  6. Deploy the MFP Adapters and Test them
  7. Run application on Android phone

Troubleshooting

Step 1. Setup Ionic and MFP CLI

Note: If you are on Windows, instead of using sudo, run the above command (and the ones below) in a command prompt opened in administrative mode.

Note: Please refer MFP documentation for compatible versions of Cordova - https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/8.0/application-development/sdk/cordova/

Step 2. Create Cloudant database and populate it with sample data

2.1 Create Cloudant database

Create Database in Cloudant NoSQL DB

Once the database is created, the dashboard will update to show the documents inside myward database (which, as expected, will be empty to begin with).


{
  "_id": "7fc63023799dfda9582609e75127b4fa",
  "reportedBy": "shivahr@gmail.com",
  "reportedDateTime": "20171125_152627",
  "picture": {
    "large": "IMG-20171125-WA0012.jpeg",
    "thumbnail": "thumbnail_IMG-20171125-WA0012.jpg"
  },
  "problemDescription": "Car parking on busy market road chocking movement of other vehicles and pedestrians",
  "geoLocation": {
    "type": "Point",
    "coordinates": [
      77.7893168,
      13.0773568
    ]
  },
  "address": "Basaveshwara Temple road (behind Market Road), Hosakote, Bangalore 562114"
}

Click Create Document to create/save the document.

The myward database should now list the six documents as shown below under Table view.

Cloudant database populated with sample data

2.2 Generate Cloudant API Key

Step 3. Create IBM Cloud Object Storage service and populate it with sample data

3.1 Create IBM Cloud Object Storage

3.2 Create Service ID and API Key for accessing objects

Step 4. Create Mobile Foundation service and configure MFP CLI

$ mfpdev server add
? Enter the name of the new server profile: Cloud-MFP
? Enter the fully qualified URL of this server: https://mobilefoundation-71-hb-server.mybluemix.net:443
? Enter the MobileFirst Server administrator login ID: admin
? Enter the MobileFirst Server administrator password: **********
? Save the administrator password for this server?: Yes
? Enter the context root of the MobileFirst administration services: mfpadmin
? Enter the MobileFirst Server connection timeout in seconds: 30
? Make this server the default?: Yes
Verifying server configuration...
The following runtimes are currently installed on this server: mfp
Server profile 'Cloud-MFP' added successfully.

$ mfpdev server info
Name         URL
--------------------------------------------------------------------------------------
Cloud-MFP  https://mobilefoundation-71-hb-server.mybluemix.net:443        [Default]
--------------------------------------------------------------------------------------

Step 5. Download source repo and customize

5.1 Clone repo

$ git clone https://github.com/IBM/Ionic-MFP-App
$ cd Ionic-MFP-App

5.2 Update App ID, Name and Description

Update IonicMobileApp/config.xml as below. Change id, name, description and author details appropriately.


<?xml version='1.0' encoding='utf-8'?>
<widget id="org.mycity.myward" version="0.0.1" xmlns="https://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:mfp="http://www.ibm.com/mobilefirst/cordova-plugin-mfp">
    <name>MyWard</name>
    <description>Get your civic issues resolved by posting through this app.</description>
    <author email="shivahr@gmail.com" href="https://developer.ibm.com/code/author/shivahr/">Shiva Kumar H R</author>
...

5.3 Specify Cloudant credentials in MFP adapter

Open MobileFoundationAdapters/MyWardData/src/main/adapter-resources/adapter.xml and update the following properties to point to the Cloudant database created in Step 2.


<mfp:adapter name="MyWardData" ...>
  <property name="account" displayName="Cloudant account" defaultValue="" />
  <property name="key" displayName="Cloudant key" defaultValue="" />
  <property name="password" displayName="Cloudant password" defaultValue="" />
  <property name="DBName" displayName="Cloudant DB name" defaultValue="myward" />
  ...
</mfp:adapter>

5.4 Specify Cloud Object Storage credentials in MFP Adapter

Open MobileFoundationAdapters/MyWardData/src/main/adapter-resources/adapter.xml and update the following properties to point to the Cloud Object Storage created in Step 3.


<mfp:adapter name="MyWardData" ...>
  ...
  <property name="endpointURL" displayName="Cloud Object Storage Endpoint Public URL" defaultValue="https://s3-api.us-geo.objectstorage.softlayer.net" />
  <property name="bucketName" displayName="Cloud Object Storage Bucket Name" defaultValue="" />
  <property name="serviceId" displayName="Cloud Object Storage Service ID" defaultValue="" />
  <property name="apiKey" displayName="Cloud Object Storage API Key" defaultValue="" />
</mfp:adapter>

Step 6. Deploy the MFP Adapters and Test them

6.1 Build and Deploy the MFP adapters

Build and deploy UserLogin adapter as below.

$ cd MobileFoundationAdapters/

$ cd UserLogin
$ mfpdev adapter build
$ mfpdev adapter deploy

Note: In Step 4, if you specified No to Make this server the default?, then you need to specify the name of your server profile (Cloud-MFP in our case) at the end of mfpdev adapter deploy command as shown below.

$ mfpdev adapter deploy Cloud-MFP

Build and deploy MyWardData adapter as below.

$ cd ../MyWardData/
$ mfpdev adapter build
$ mfpdev adapter deploy

6.2 Launch MFP dashboard and verify adapter configurations

Launch MFP Dashboard as below:

Verify MFP Adapter configuration as below:

6.3 Test the MyWardData adapter

Create temporary credentials to test adapter REST API as below:

Test adapter REST API as below:

Delete the temporary credentials after testing adapter REST API as below:

Step 7. Run application on Android phone

7.1 Install Android Studio and Android SDK platform


  <preference name="android-minSdkVersion" value="16" />
  <preference name="android-targetSdkVersion" value="23" />
### 7.2 Enable developer options and USB debugging on your Android phone * Enable USB debugging on your Android phone as per the steps in https://developer.android.com/studio/debug/dev-options - Launch the Settings app on your phone. Select `About Device` -> `Software Info`. Tap `Build number` 7 times to enable developer options. - Return to Settings list. Select `Developer options` and enable `USB debugging`. * If you are developing on Windows, then you need to install the appropriate USB driver as per instructions in https://developer.android.com/studio/run/oem-usb. * Connect the Android phone to your development machine by USB cable, and accept `allow` access on your phone. ### 7.3 Setup API keys for using Google Maps * Get an API key for using the Google Maps Android API as per instructions in https://developers.google.com/maps/documentation/android-sdk/signup. You can similarly get an API key for using the Google Maps SDK for iOS as per instructions in https://developers.google.com/maps/documentation/ios-sdk/get-api-key. * Add the Google Maps API keys into the `MyWard` app as below: ``` $ cd ../../IonicMobileApp/ $ ionic cordova plugin add cordova-plugin-googlemaps --variable API_KEY_FOR_ANDROID="" --variable API_KEY_FOR_IOS="" PLAY_SERVICES_VERSION=15.0.1 ``` Note: Make sure you specify the latest PLAY_SERVICES_VERSION in the command above. ### 7.4 Enable Android platform for Ionic application * Add [Cordova platform for Android](https://cordova.apache.org/docs/en/latest/guide/platforms/android/) ``` $ cd ../IonicMobileApp $ ionic cordova platform add android@6.3.0 > cordova platform add android@6.3.0 --save ... ``` Note: Make sure the Cordova platform version being added is supported by the MobileFirst plug-ins. Site https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/8.0/application-development/sdk/cordova/ lists the supported levels. ``` $ cordova platform version Installed platforms: android 6.3.0 Available platforms: blackberry10 ~3.8.0 (deprecated) browser ~4.1.0 ios ~4.4.0 osx ~4.0.1 webos ~3.7.0 ``` ### 7.5 Register the MyWard app to MFP server ``` $ cd ../IonicMobileApp $ mfpdev app register Verifying server configuration... Registering to server:'https://mobilefoundation-71-hb-server.mybluemix.net:443' runtime:'mfp' Updated config.xml file located at: .../Ionic-MFP-App/IonicMobileApp/config.xml Run 'cordova prepare' to propagate changes. Registered app for platform: android ``` Note: In [Step 4](#step-4-create-mobile-foundation-service-and-configure-mfp-cli), if you specified `No` to `Make this server the default?`, then you need to specify the name of your server profile (`Cloud-MFP` in our case) at the end of `mfpdev app register` command as shown below. ``` $ mfpdev app register Cloud-MFP ``` Propagate changes by running `cordova prepare` ``` $ ionic cordova prepare ``` ### 7.6 Build/Run the Ionic application on Android phone * Build Android application ``` $ cd ../IonicMobileApp $ ionic cordova build android ```  Note: In case the Cordova build fails due to missing `ANDROID_HOME` and `JAVA_HOME` environment variables, then set those environment variables as per instructions in https://cordova.apache.org/docs/en/latest/guide/platforms/android/#setting-environment-variables. `ANDROID_HOME` should be set to the `Android SDK Location` that you noted in [Step 7.1](#71-install-android-studio-and-android-sdk-platform). Command `/usr/libexec/java_home` returns the value to be used for setting `JAVA_HOME` on [macOS](https://mattshomepage.com/articles/2016/May/22/java_home_mac_os_x/). On other platforms you could run `java -XshowSettings:properties 2>&1 | grep 'java.home'` as mentioned [here](http://sbndev.astro.umd.edu/wiki/Finding_and_Setting_JAVA_HOME#Sample_Perl_Script:_java_home). * Run application on Android device ``` $ ionic cordova run android ``` MyWard App - Login Page MyWard App - Home Page MyWard App - Problem Detail Page MyWard App - Report New Problem Page ### 7.7 Update App Logo and Splash Reference: Automating Icons and Splash Screens https://blog.ionicframework.com/automating-icons-and-splash-screens/ Copy your desired app icon to `IonicMobileApp/resources/icon.png` and app splash to `IonicMobileApp/resources/splash.png`. ``` $ cd ../IonicMobileApp $ ionic cordova resources ``` For running `ionic cordova resources` command, you would need to sign up on [ionicframework.com](https://ionicframework.com/) and specify the credentials on the command line. ### 7.8 Build APK for uploading to Google Play Store Reference: https://ionicframework.com/docs/intro/deploying/ * Add following lines at the end of `IonicMobileApp/platforms/android/proguard-project-mfp.txt`: ``` -dontwarn okhttp3.internal.huc.** -keep class plugin.google.maps.** { *; } ``` * Create release build as below: ``` $ cd ../IonicMobileApp $ ionic cordova build android --prod --release ``` * Set `ANDROID_HOME` environment variable as per instructions in [Step 7.6](#76-buildrun-the-ionic-application-on-android-phone). On Mac, this is usually: ``` export ANDROID_HOME=/Users//Library/Android/sdk ``` * Zip align release build as below: ``` $ cd ./platforms/android/build/outputs/apk/ $ ls android-release-unsigned.apk $ $ANDROID_HOME/build-tools/23.0.3/zipalign -v -p 4 android-release-unsigned.apk android-release-unsigned-aligned.apk $ ls android-release-unsigned-aligned.apk android-release-unsigned.apk ``` * Create self signing certificate as below: Make a note of the `Keystore password` that you set. You would need it for signing your APK. ``` $ keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias Enter keystore password: Re-enter new password: What is your first and last name? [Unknown]: Shiva Kumar H R What is the name of your organizational unit? [Unknown]: ISL What is the name of your organization? [Unknown]: IBM What is the name of your City or Locality? [Unknown]: Bangalore What is the name of your State or Province? [Unknown]: Karnataka What is the two-letter country code for this unit? [Unknown]: IN Is CN=Shiva Kumar H R, OU=ISL, O=IBM, L=Bangalore, ST=Karnataka, C=IN correct? [no]: yes Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 10,000 days for: CN=Shiva Kumar H R, OU=ISL, O=IBM, L=Bangalore, ST=Karnataka, C=IN Enter key password for (RETURN if same as keystore password): [Storing my-release-key.jks] $ ls android-release-unsigned-aligned.apk android-release-unsigned.apk my-release-key.jks ``` * Self sign APK as below: ``` $ $ANDROID_HOME/build-tools/23.0.3/apksigner sign --ks my-release-key.jks --out myward.apk android-release-unsigned-aligned.apk Keystore password for signer #1: $ ls android-release-unsigned-aligned.apk my-release-key.jks android-release-unsigned.apk myward.apk $ ``` * Distribute `myward.apk` by uploading to Google Play Store or to your company's internal App store. # Troubleshooting Please see [troubleshooting guide](TROUBLESHOOTING.md) for solutions to some commonly occuring problems. ### Debugging Android hybrid app using Chrome Developer Tools * Install Google Chrome * Open Google Chrome. Open URL chrome://inspect/#devices * Under `Devices`, click on `inspect` below your connected device. Debugging of Android app using Chrome Developer Tools # References * [Speeding up development of your enterprise mobile apps using open source technologies and cloud services](https://developer.ibm.com/code/2018/02/08/speeding-development-enterprise-mobile-apps-using-open-source-technologies-cloud-services/) * [MobileFirst Foundation 8.0 Developer Labs](https://mobilefirstplatform.ibmcloud.com/labs/developers/8.0/intro/) * Ionic 2 quick tutorials: - [10 Minutes with Ionic 2: Hello World](https://blog.ionicframework.com/10-minutes-with-ionic-2-hello-world/) - [10 Minutes with Ionic 2: Adding Pages and Navigation](https://blog.ionicframework.com/10-minutes-with-ionic-2-adding-pages-and-navigation/) - [10 Minutes with Ionic 2: Calling an API](https://blog.ionicframework.com/10-minutes-with-ionic-2-calling-an-api/) - [10 Minutes with Ionic 2: Using the Camera with Ionic Native](https://blog.ionicframework.com/10-minutes-with-ionic-2-using-the-camera-with-ionic-native/) * [What Does Ionic 3 Mean for Ionic 2?](https://www.joshmorony.com/what-does-ionic-3-mean-for-ionic-2/) * [Dealing with Asynchronous Code in Ionic](https://www.joshmorony.com/dealing-with-asynchronous-code-in-ionic/) * [Understanding Zones and Change Detection in Ionic 2 & Angular 2](https://www.joshmorony.com/understanding-zones-and-change-detection-in-ionic-2-angular-2/) * [Basic Security for Ionic & Cordova Applications](https://www.joshmorony.com/basic-security-for-ionic-cordova-applications/) # License This code pattern is licensed under the Apache Software License, Version 2. Separate third party code objects invoked within this code pattern are licensed by their respective providers pursuant to their own separate licenses. Contributions are subject to the [Developer Certificate of Origin, Version 1.1 (DCO)](https://developercertificate.org/) and the [Apache Software License, Version 2](https://www.apache.org/licenses/LICENSE-2.0.txt). [Apache Software License (ASL) FAQ](https://www.apache.org/foundation/license-faq.html#WhatDoesItMEAN)