Skip to Content
Technical Articles
Author's profile photo Daniel Van Leeuwen

Appendix E: Non Kapsel Plugins

Previous   Home   Next

The following examples demonstrate how to include and use some of the native functionality that Cordova plugins provide.

Taking, Storing and Retrieving a Picture
Acquiring the Device Location and Displaying it on a Map

Taking, Storing and Retrieving a Picture

The following steps demonstrate how to take a picture using the Cordova camera plugin and how to store and retrieve previously taken images.

  • Create a new project named CameraDemo and add Android or iOS or both.
    cordova create C:\Kapsel_Projects\CameraDemo com.mycompany.camera CameraDemo
    cd CameraDemo
    cordova platform add android
    
    cordova create ~/Documents/Kapsel_Projects/CameraDemo com.mycompany.camera CameraDemo
    cd ~/Documents/Kapsel_Projects/CameraDemo
    cordova platform add ios
  • Add the Kapsel Encrypted Storage plugin, the Cordova Camera and Dialogs plugins.
    cordova plugin add cordova-plugin-camera
    cordova plugin add cordova-plugin-dialogs
    
    cordova plugin add kapsel-plugin-encryptedstorage --searchpath %KAPSEL_HOME%/plugins
    or
    cordova plugin add kapsel-plugin-encryptedstorage --searchpath $KAPSEL_HOME/plugins
    
  • Replace the contents of index.html with the below code.
    <html>
    <head>
        <title>Camera Demo</title>
        <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
        <script>
        var selectEl = null;
        var imageEl = null;
        var store = null;
        var firstTime = null;
        
        function onLoad() {
            selectEl = document.getElementById("imageNumSelect");
            imageEl = document.getElementById("imageID");
        }
    
        function addOption(select, text, value) {
            var option = document.createElement("option");
            option.text = text;
            option.value = value;
            select.options.add(option);
            select.selectedIndex = select.options.length - 1;
            showImage();
        }
    
        function populateSelectFromStore() {
            store.length(function(length) {
                for (var i = 0; i < length; i++) {
                    store.key(i, function(key) {
                        addOption(selectEl, key, key);
                    }, onFail);
                }
            }, onFail);
        }
    
        function deletePhoto() {
            var selectedValue = selectEl.options[selectEl.selectedIndex].value;
            store.removeItem(selectedValue, successCallback, onFail);
            selectEl.options.remove(selectEl.selectedIndex);
            showImage();
        }
    
        function showImage() {
            if (selectEl.options.length == 0) {
                imageEl.src = "data:image/jpeg;base64,";
                return;
            }
            var selectedValue = selectEl.options[selectEl.selectedIndex].value;
            store.getItem(selectedValue, function(imageData) {
                imageEl.src = "data:image/jpeg;base64," + imageData;
            }, onFail);
        }
    
        function capturePhoto() {
            firstTime = true;
            navigator.camera.getPicture(onSuccess, onFail, { quality: 85, allowEdit: true, targetWidth : 399, targetHeight : 300, sourceType: navigator.camera.PictureSourceType.CAMERA, destinationType: navigator.camera.DestinationType.DATA_URL });
        }
    
        function onSuccess(imageData) {
            if (firstTime) {  //method is called twice on iOS.  Not sure why.
                firstTime = false;
            
                imageEl.src = "data:image/jpeg;base64," + imageData;
                var imageName = prompt("Please enter a name for the image",""); //prompt doesn't work on Windows.  Need to use navigator.notification.prompt and handle async.
                //store image
                store.setItem(imageName, imageData, successCallback, onFail);
                //update dropdown
                addOption(selectEl, imageName, imageName);
            }
        }
    
        function onFail(message) {
            firstTime = false;
            navigator.notification.alert("Failed because: " + message);
        }
        
        function init() {
            var appId = "com.mycompany.camera"; // Change this to app id on server
            var context = {
                  "passcode": "password",  //Note hardcoding passwords and unlock passcodes are strictly for ease of use during development
                                           //Once set can be changed by calling sap.Logon.managePasscode()
                  "unlockPasscode": "password",
                  "passcode_CONFIRM":"password",
            };
        
            var passcodePolicy = {
                  "expirationDays":"0",
                  "hasDigits":"false",
                  "hasLowerCaseLetters":"false",
                  "hasSpecialLetters":"false",
                  "hasUpperCaseLetters":"fales",
                  "defaultAllowed":"true",
                  "lockTimeout":"300",  //5 minutes, if this is set too low (0), the data vault could be locked when coming back from the camera app and storing the picture will fail. 
                  "minLength":"6",
                  "minUniqueChars":"0",
                  "retryLimit":"0"
            };
            
            //Used if the application is not registering with the SMP 3.0 server.  New to SP03.
            sap.Logon.initPasscodeManager(logonSuccessCallback, errorCallback, appId, null, passcodePolicy, context);
        }
        
        function logonSuccessCallback() {
            store = new sap.EncryptedStorage("testStore");
            populateSelectFromStore();
        }
        
        function successCallback() {
        }
        
        function errorCallback(error) {
            navigator.notification.alert("An error occurred:  " + JSON.stringify(error));
        }
        
        document.addEventListener("deviceready", init, false);
        </script>
    </head>
    <body onload="onLoad()">
        <button onclick="capturePhoto();">Capture Photo</button><br>
        <button onclick="deletePhoto();">Delete Photo</button><br>
        <select id="imageNumSelect" onchange="showImage()";>
        </select><br>
        <img src="" id="imageID">
    </body>
    </html>
    
  • Prepare, build and deploy the app with the following commands.
    cordova run android
    or
    cordova run ios

Acquiring the Device Location and Displaying it on a Map

The following steps demonstrate how to get a location and then use Google services to translate a location into an address and to display a map showing the address.

  • Create a new project named LocationDemo and add Android or iOS or both.
    cordova create C:\Kapsel_Projects\LocationDemo com.mycompany.location LocationDemo
    cd LocationDemo
    cordova platform add android
    
    cordova create ~/Documents/Kapsel_Projects/LocationDemo com.mycompany.location LocationDemo
    cd ~/Documents/Kapsel_Projects/LocationDemo
    cordova platform add ios
  • Add the InAppBrowser plugin to the project to enable showing the Google Map in a separate window that will have a close button. Also add the Dialogs and geolocation plugins.
    cordova plugin add cordova-plugin-inappbrowser
    cordova plugin add cordova-plugin-dialogs
    cordova plugin add cordova-plugin-geolocation
  • Replace the contents of index.html with the code below.
    <html>
    <head>
        <title>Location Demo</title>
        <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
    
        <script>
    	    function getLocation() {
    	        navigator.geolocation.getCurrentPosition(locSuccess, locFail, {maximumAge:10000, timeout:30000, enableHighAccuracy: true});
    	    }
    	    
    	    function getAddress() {
    	        var lat = document.getElementById("latitude").value; 
    	        var long = document.getElementById("longitude").value;
    	        var url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + lat + "," + long + "&sensor=false";
    	        //var url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=  &sensor=false"
                var xmlhttp = new XMLHttpRequest();
                xmlhttp.open("GET", url, false);
                try {
                    xmlhttp.send();
                }
                catch (e) {
                    navigator.notification.alert(JSON.stringify(e));
                    return;
                }
                var responseText = xmlhttp.responseText;
                var responseObj = JSON.parse(responseText);
                var address = responseObj.results[0].formatted_address;
                document.getElementById("address").value = address;
    	    }
    	    
    	    function locSuccess(position) {
    	        var latitude = position.coords.latitude;
    	        var longitude = position.coords.longitude;
    	        document.getElementById("latitude").value = latitude;
    	        document.getElementById("longitude").value = longitude;
    	    }
    	        
    	    function locFail(error) {
    	        console.log(JSON.stringify(error));
    	        navigator.geolocation.getCurrentPosition(locSuccess, locFail2, {maximumAge:10000, timeout:30000, enableHighAccuracy: false});
    	    }  
    	    
    	    function locFail2(error) {
                console.log(JSON.stringify(error));
                console.log("Failed to establish the device's location");
            } 
            
            function showStaticMap() {
                var lat = document.getElementById("latitude").value;
                var long = document.getElementById("longitude").value;
                var img_url="https://maps.googleapis.com/maps/api/staticmap?center=";
                img_url = img_url + lat + "," + long + "&zoom=14&size=400x300&sensor=false";
                document.getElementById("mapholder").innerHTML="<img src='"+img_url+"'>";
            }
            
            function showFullMap() {
                var lat = document.getElementById("latitude").value;
                var long = document.getElementById("longitude").value;
                var URLToOpen = encodeURI("https://maps.google.com/?q=" + lat + "," + long);  //may be needed if URL contains parameters 
                var ref = window.open(URLToOpen, '_blank    ', 'location=yes');  //location bar shown or not  //use _system if you wish to open in the system browser.
            } 
        </script>
    </head>
    <body><br><br>
        <button onclick="getLocation();">Get Location</button><br>
        <button onclick="getAddress();">Get Address from Location</button><br>
        Latitude:<input type="text" id="latitude"><br>
        Longitude:<input type="text" id="longitude"><br>
        Address:<textarea rows="2" cols="30" id="address"></textarea><br>
        <button onclick="showStaticMap()">Show Static Map</button>
        <button onclick="showFullMap()">Show Full Map</button>
        <div id="mapholder"></div>
    </body>
    </html>
  • Prepare, build and deploy the app with the following commands.
    cordova run android
    or
    cordova run ios

    If you are using Windows Phone, enable the location capability as shown below.

    If using an Android emulator, the emulator’s location can be changed from the emulator’s extended controls under location.

    On an iOS simulator the location can be changed under Debug > Location.

  • Depending on the device, the location may not be returned before the timeout occurs.

    On Android, ensure that the Location is enabled under Settings > Location > On. The Mode can also be set. Finally under recent location requests should appear LocationDemo if you have previously pressed the Get Location button.
    On iOS, ensure that Location is enabled under Settings > Privacy > Location > Location Service > On

Previous   Home   Next

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Hello Daniel,

      I tried to build the application using cordova camera plugin. The camera plugin is not responding when we are accessing through the SAP fiori client in android mobile device.

      Can you please suggest.

      Thanks,

      Gurung

      Author's profile photo Daniel Van Leeuwen
      Daniel Van Leeuwen
      Blog Post Author

      What version of Android is the device running on?

      What version of the Kapsel SDK are you using?

      Does the app have permission to access the camera?  This permission should be asked for the first time the app attempts to use the camera.

      I believe you could also give this setting on the device by going to settings > Apps > your_app > Permissions.

      I would recommend getting the latest patch for the 14 release of the Kapsel SDK if you haven't already.

      Regards,

      Dan van Leeuwen

      Author's profile photo Former Member
      Former Member

       

      Hello Daniel,

       

      Thank you so much for prompt reply.

      Android version : 6.0.1

      The application is based out of HANA XS engine and  configured in SAP HANA Launchpad.

      SAP Fiori client access the SAP HANA Launchpad URL to access  the application.

      Yes the SAP fiori client has permission to access the camera.

      cordova version :  6.1.2

       

      Thanking you.

      Thanks,

      Gurung

       

      Author's profile photo Daniel Van Leeuwen
      Daniel Van Leeuwen
      Blog Post Author

      I would recommend doing a cordova plugins and checking the version of the camera plugin.

       

      I did find mention of an issue.  Could this be related?  Perhaps you could change the version of the camera plugin being used in your project.

       

      The latest Cordova camera plugin (2.3.1) cannot be built with the Kapsel Logger plugin.

      Element provider#android.support.v4.content.FileProvider at AndroidManifest.xml:40:9-42:20 duplicated with element declared at AndroidManifest.xml:12:9-14:20

      /Users/i827005/androidtest/platforms/android/AndroidManifest.xml Error:

      With 2.3.0 of the camera plugin I can build successfully.

       

      Regards,
      Dan van Leeuwen