/wp-content/uploads/2014/06/sap_logo_333927.png

Online Application (New in SP04)

This plugin adds the include for cordova.js to the HTML page being loaded.  This makes it easier to enhance an existing hosted web app by running it inside a Cordova container enabling access to native device functionality.  For additional details see Using the Online Application Plugin.

Imagine that you have an existing application that is being hosted by a web server.  Because it is an HTML5 app it can be accessed from multiple platforms and on multiple devices (for example Windows, Mac, Android and iOS devices).  It is also easy to update the app as after a new fix or feature is added to the website it immediately becomes available to all users the next time they load the app.

You now have a new feature request that when run on a mobile device, the battery level and network should be checked before executing a potentially long running operation so that the user can opt to not execute the operation.  There are multiple ways that this new feature request could be implemented.  The following three examples Packaging the Content in a Hybrid App, Loading the Content from a Web Server, and  Using the Online Application Plugin will demonstrate a few of the ways that this feature request could be implemented.

The sample from the Appendix A: OData will be extended.  Follow the instructions below to host the products.html file in a web server.

  • Create a folder in which to host the sample web app such as C:\ODataSample.
  • Copy the products.html and datajs-1.1.2.min.js files into this folder.  The source for products.html can be copied from the previously mentioned OData appendix.
  • Install a web server like the http-server.
    npm install -g http-server
    or
    sudo npm install -g http-server
  • Start the web server
    http-server C:\ODataSample -c-1 -p 80
    or
    sudo http-server ~/Documents/ODataSample -c-1 -p 80

    Where -c minus one indicates to disable caching and -p indicates the port to use.
    Note it is useful to disable caching during development when the website content is being frequently changed.

  • Open the page in browser such as Chrome using the following URL.
    http://localhost/products.html

    image0.PNG

Packaging the Content in a Hybrid App

One way for an HTML5 application to access native device functionality is to create a Cordova project which contains the content of the app plus the Cordova plugins that expose native device functionality via JavaScript calls.  With this approach the app is now packaged and installed on the device as a regular app (rather than being opened via the browser).  The content is loaded from the device rather than from a web server and hence reduces network usage, decreases load time and could potentially be used when the device does not have a network connection.  The development effort to support offline use cases is made much easier with the Offline OData plugin.  Updates to the HTML5 content of the application can be distributed to the app by using the Kapsel AppUpdate plugin.

Perform the following steps to enable the products.html app to check the battery level and network by having the HTML5 resources of the app (products.html and datajs-1.1.2.min.js) be loaded from the device’s file system.

  • Create the project.
    cordova -d create C:\Kapsel_Projects\ProductsDemo1 com.mycompany.products1 ProductsDemo1 "{\"plugin_search_path\":\"C:/SAP/MobileSDK3/KapselSDK/plugins/\"}"
    cd C:\Kapsel_Projects\ProductsDemo1
    cordova -d platform add android
    
    cordova -d create ~/Documents/Kapsel_Projects/ProductsDemo1 com.mycompany.products1 ProductsDemo1 "{\"plugin_search_path\":\"/Users/i826567/SAP/MobileSDK3/KapselSDK/plugins/\"}"
    cd ~/Documents/Kapsel_Projects/ProductsDemo1
    cordova -d platform add ios
  • Add the battery status and network information plugins.
    cordova plugin add https://github.com/apache/cordova-plugin-battery-status
    cordova plugin add https://github.com/apache/cordova-plugin-network-information
  • Copy the products.html and datajs-1.1.2.min.js files from C:\ODataSample to C:\Kapsel_Projects\ProductsDemo1\wwww.
  • Create a new file named C:\Kapsel_Projects\ProductsDemo1\wwww\utils.js that contains the contents in utils.js.
  • Modify C:\Kapsel_Projects\ProductsDemo1\wwww\products.html.  Add the below two includes.
    <script src="cordova.js"></script>
    <script src="utils.js"></script>
    

    Replace the existing body tag with the below two lines.

    <body>
    <button onclick="if (statusCheck()) {init();}">Perform Some Long Running Network Operation</button>
  • Modify C:\Kapsel_Projects\ProductsDemo1\config.xmlto load the products.html file rather than index.html.  Specifically modify the content tag to
    <content src="products.html"/>
  • Copy the contents of the www folder to the platform specific www folder of the project using prepare.
    cordova -d prepare
  • Use the Android IDE or Xcode to deploy and run the project.

    image1.PNG

  • Note, the battery level will only be set when the level changes by one percent.  If this is being run on an Android emulator, you can set the battery level by telnetting to the host shown in the top left of the emulator title.
    telnet localhost 5444
    power capacity 5
    

    Note, if the above command does not have an effect, edit C:\Users\user\.android\avd\Android_4_4.avd\config.ini and ensure that the setting hw.battery is set to yes and restart the emulator.

  • At this point, there are now two different versions of product.html which is not ideal.  One is included in the hybrid app and one that is served by the web server.

Loading the Content from a Web Server

A slightly different way to implement this feature would be to have the Cordova WebView (browser) load the content from the web server instead of including the HTML5 files as part of the app.  The app would detect that it is being loaded in a Cordova container and then dynamically include cordova.js and utils.js.
If the device used to access the app does not always have an internet connection, the app could be configured to use the HTML5 application cache.

Perform the following steps to enable the products.html app to check the battery level and network by having all the HTML5 resources be loaded from a web server.

  • Modify C:\Kapsel_Projects\ProductsDemo1\config.xmlto load the page from the web server.  Specifically modify the content tag to something like
    <content src="http://10.7.171.223/products2.html?cordova=true"/>

    Note, the ?cordova=true will enable the JavaScript code to detect that it is being run in a Cordova container as opposed to a browser on a mobile device.

  • Copy C:\ODataSample\products.html to products2.html.
    Copy C:\Kapsel_Projects\ProductsDemo1\wwww\utils.js to C:\ODataSample\utils.js.
    Copy the below files and folder to C:\ODataSample.
    C:\Kapsel_Projects\ProductsDemo1\platforms\android\assets\www\cordova.js
    C:\Kapsel_Projects\ProductsDemo1\platforms\android\assets\www\cordova_plugins.js
    C:\Kapsel_Projects\ProductsDemo1\platforms\android\assets\www\plugins
    
  • Modify C:\ODataSample\products2.html. Add the below code before successCallback method.
    var isCordova = location.search.split('cordova=')[1];
    
    //load cordova.js and utils.js if we are being run in a Cordova container
    if (isCordova) {
        var head = document.getElementsByTagName('HEAD').item(0);       
        var script = document.createElement('script');
        var script2 = document.createElement('script');
        //script.src = "file://android_asset/www/cordova.js";  //get permission error on Android which is why we are loading Cordova files from web server.
        script.src = "cordova.js";
        script2.src = "utils.js";
        head.appendChild(script);
        head.appendChild(script2);
        //script2.onload = function () { }
    }
    

    Replace the previous init method with the new code below code.

    function init() {
        var div = document.createElement('div');
        if (isCordova) {
            div.innerHTML = '<button onclick="if (statusCheck()) loadData();">Perform Some Long Running Network Operation</button>';
        }
        else {
            div.innerHTML = '<button onclick="loadData();">Load Data</button>';
        }
        document.body.appendChild(div);
    }

    function loadData() {
        OData.defaultHttpClient.enableJsonpCallback=true;  //
    http://datajs.codeplex.com/wikipage?title=OData%20Security&referringTitle=Cross%20Domain%20Requests
        OData.read("http://services.odata.org/OData/OData.svc/Products", successCallback, errorCallback);
    }
  • Copy the contents of the www folder to the platform specific www folder of the project using prepare.
    cordova -d prepare
  • Use the Android IDE or Xcode to deploy and run the project.
    When viewed in the debugger it is possible to verify where the files were loaded from.  Note below cordova.js was loaded from a web server.
    image2.PNG

    Note the following is how the app appears when loaded from a browser.  Notice that cordova.js and utils.js are not loaded.
    image4.PNG

  • Try shutting down the webserver and then opening the app.  Notice that the following error occurs after 60 seconds. 
    image7.PNG

    On Android, it is possible to configure the length of the timeout and the error page to show when a timeout occurs by modifying C:\Kapsel_Projects\ProductsDemo1\config.xmlwith the following parameters and by adding an error.html page.

        <preference name="loadUrlTimeoutValue" value="3000" />
        <preference name="errorUrl" value="file:///android_asset/www/error.html" />
    

    On iOS, a blank screen is shown and in the Xcode console a message appears saying “Failed to load webpage with error:  Could not connect to the server”.

  • The file cordova.js is platform specific so in order for this to work across more than one platform, code would need to be added to detect the platform and include the appropriate cordova.js.  Additionally cordova.js should match the version of the Cordova container so this solution is not ideal.
  • The next section demonstrating the online application simplifies the process of including the cordova.js file and provides an HTML page that will be shown when the webserver is not available.

Using the Online Application Plugin

The Online Application plugin provides the code used to dynamically add the cordova.js include automatically and enables the cordova.js and other JavaScript files required by the added plugins to be loaded from the device’s file system rather than from a web server as was shown in the above example.  It also provides a busy indicator and can be used to append a string to the user agent.

Perform the following steps to enable the products.html app to check the battery level and network by having all of the app’s files load from the web server and the Cordova plugin specific JavaScript load from the device’s file system.  For a more complete example see the Fiori Client implementation.

  • Modify C:\Kapsel_Projects\ProductsDemo1\config.xml to something like
    <content src="http://10.7.171.223/products3.html"/>
  • Add an entry just above the name element to C:\Kapsel_Projects\ProductsDemo1\config.xml
    <preference name="UserAgentSuffix" value="cordova" />
    <preference name="useBusyIndicator" value="true" />

    Note this is using the Online Application plugin user agent feature and can be used as another method to determine that the app is being run in a Cordova container.  By changing the user agent, it would be possible to calculate the number of users using a Cordova container to access the app and it would also be possible for the web server to serve a different version of the app when it detects that the app is being run in a Cordova container.
    With the preference useBusyIndicator set to true, a spinner will be shown when the products3.html and its required files are being loaded. Note it is also possible to explicitly show and hide the spinner with calls to sap.Online.showBusyIndicator() and sap.Online.hideBusyIndicator().

  • Copy C:\ODataSample\products2.html to products3.html.
  • Replace the line
    var isCordova = location.search.split('cordova=')[1];

    with

    var isCordova = navigator.userAgent.indexOf("cordova") == 0;
    

    This is using the user agent feature of the Online Application plugin.

  • Add an include for utils.js to products3.html by adding <script src=”utils.js”></script>

    Remove the code to dynamically include cordova.js and utils.js by deleting the 11 lines starting with if (isCordova) {

  • Add the Online Application plugin.
    cordova -d plugin add com.sap.mp.cordova.plugins.online
    
  • Copy the contents of the www folder to the platform specific www folder of the project using prepare.
    cordova -d prepare
  • Use the Android IDE or Xcode to deploy and run the project.
    When viewed in the debugger it is possible to verify where the files were loaded from.  Note below that cordova.js file is not loaded from the webserver.
    image3.PNG
    Also note that the suffix added to the user agent string can be seen in the Web Inspector.

  • Try shutting down the webserver and then opening the app.  Notice that on iOS the error page named CannotReachHost.html is opened now. 
    Note that in SP08, for this page to render correctly, the logon and apppreferences plugins need to be added.
    image8.PNG
  • The version of the Cordova container and the version of cordova.js should be the same.  This technique ensures that these files are kept at the correct version.
  • To prevent injecting the cordova and Kapsel plugins in a HTML page add the following to the page.
    <script type="text/javascript">
         window.cordova= true;
    </script>
    

Back to Getting Started With Kapsel

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. jitendra kansal

    Hi Daniel,

    I was trying first approach after modifying products.html file inside WWW folder. When i launch the project in Android emulator, i dont see “Name Description Price” labels in the simulator as you have showed in that screenshot.

    androidSimulator.PNG

    Are files & folders inside WWW folder correct?

    www.PNG

    Rgrds,

    JK

    (0) 
    1. Daniel Van Leeuwen Post author

      Looks good to me.  Did you chance remove the <table> tag from the original products.html file?

      <table id=”productsTable”><tr><th>Name</th><th>Description</th><th>Price</th></tr></table>

      (0) 
  2. Daniel Van Leeuwen Post author

    Updated for SMP SDK 3.0 SP08. 

    Added reference to busy indicator feature new to SP08 and UserAgentSuffix rather than UserAgentPrefix is the preferred method for modifying the user agent.

    (0) 

Leave a Reply