Skip to Content
Technical Articles
Author's profile photo Dennis Koehler

Providing native barcode scanning on SAP Mobile Start (SAPUI5 & Quagga.js)

Hey everyone!

SAP Fiori Client is going to be removed from app store and google play as mentioned in note 2992772. While it must be noted that SAP Mobile Start is NOT a replacement for the SAP Fiori Client, it is quite natural that SAP Mobile Start will be used as entry point for the mobile users going forward.

Since standard SAPUI5 Barcode Scanning functionalities of SAPUI5 versions below 1.92.0 are reliant on Cordova plugin (accessible via SAP Fiori Client), any apps below version 1.92.0 that are utilizing these features won’t be supported by standard browsers or SAP Mobile Start. The customers who are using native features like camera integration for barcode scanning via SAP Fiori Client must therefore look at other alternatives like QuaggaJS and ZXingJS as suggested in the note.

This blog will help you to make use of one of these alternatives. I will explain how I’ve created a custom SAP UI5 app that uses QuaggaJS library and can be launched on iPhone and iPad using SAP Mobile Start:

This will cover the following:

  • Creation of a simple SAPUI5 App in SAP Business Application Studio
  • Deployment to BTP Subaccount
  • Making the app available in SAP Launchpad Service site
  • Launch the app from SAP Mobile Start

 

Prerequisites:

    • Technical:
      • SAP BTP Subaccount with
        • Subscription to SAP Launchpad Service & Business Application Studio
        • Cloud Foundry Org and Space for custom apps deployment
    • Knowledge
      • Basic SAPUI5 Programming / Business Application Studio
      • (optional) SAP Launchpad Service

 

1. Creation of Simple SAPUI5 Barcode Scanning App

 

For my own first try of the barcode functionality as part of an POC, I followed this blospost by Ian MacGregor. He provides further inside on the apps development.
Note that this is an example for the most basic app you could think of and the project settings might be different for other purposes. I will explain how to create a project in SAP Business Application Studio and how to deploy to BTP subaccount.

 

1.1 Create Empty SAP Fiori Project in Business Application Studio

 

Once you are in the Business Application Studio create a new Dev Space for SAP Fiori:

SAP%20Fiori%20space%20on%20Business%20Application%20Studio

SAP Fiori space on Business Application Studio

Launch it by clicking the title. You will see a welcome page, where you can create a new project from template:

  1. Select Template and Target Location:           
    • SAP Fiori application

  2. Floorplan Selection
    • Application Type: SAPUI5 freestyle
    • Floorplan: SAPUI5 Application
  1. Data Source and Service Selection:
    • None
  2. View name:
    • BarcodeScanner (Or something else you prefer)
  3. Project Attributes:
    • Provide module name and application title
      (Make sure to tick “Yes” for “Add
      deployment configuration”
      and “Add FLP
      configuration”
      .)


  1. Deployment Configuration
    • Target:  Cloud Foundry
    • Destination: None
    • Add application to managed application router: Yes

  1. Fiori Launchpad Config:
    • Semantic Object:  barcode
    • Action:      scan
    • Title:         Barcode Scanner
    • Subtitle:   POC for SAP Mobile Start

 

1.2 Develop Basic Barcode Scanning App

 

First you need to download the latest version of Quagga.js library from here.
Download the page and you will get the quagga.min.js file.

Open the project folder in a workspace, so that you can proceed with the development.
Once you are in the workspace go to the webapp folder, create a subfolder named libs and paste the downloaded quagga.min.js file there. Your folder should look like this:

 

 

Next, open the manifest.json file and search for the “resources” node and add the path to the library:

"resources": {
            "css": [
                {
                    "uri": "css/style.css"
                }
            ], 
            "js": [
                {
                    "uri": "libs/quagga.min.js"
                }
            ]
        },

In the folder webapp > model > models.js replace the createDeviceModel function with this one:

createDeviceModel: function () {
     var oModel = new JSONModel(Device);
     oModel.setDefaultBindingMode("OneWay");
        
     // Disable the scan barcode button by default
     oModel.setProperty("/barcodeScanEnabled",false);
            
     if(navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia){
          navigator.mediaDevices.getUserMedia({video:true}).then(function(stream){
             // device supports video, which means will enable the scan button
             oModel.setProperty("/barcodeScanEnabled",true);
          }).catch(function(err){
             // not supported, barcodeScanEnabled already default to false
          });
      }    
    return oModel;
}

 

On webapp > view > BarcodeScanner.view.xml add the following Label, Input and Button to the <Page>-Tag:
(Just replace the <content/> tag by the below)

<Label text="Barcode value" />
<Input id="scannedValue" placeholder="Use scan button to enter barcode" />
<Button icon="sap-icon://bar-code" text="Scan" tooltip="Scan barcode" press="onScanForValue">
</Button>

 

On webapp > controller >BarcodeScanner.controller.js add the following functions below the onInit-function:

(Note: In this code snipped also the QR-Code format get’s selected. In this case the standard “code_128_reader”, you can change the format by adding different readers from Quagga.js documentation)

onScanForValue: function (oEvent) {
                if (!this._oScanDialog) {
                    this._oScanDialog = new sap.m.Dialog({
                        title: "Scan barcode",
                        contentWidth: "640px",
                        contentHeight: "480px",
                        horizontalScrolling: false,
                        verticalScrolling: false,
                        stretchOnPhone: true,
                        content: [new sap.ui.core.HTML({
                            id: this.createId("scanContainer"),
                            content: "<div />"
                        })],
                        endButton: new sap.m.Button({
                            text: "Cancel",
                            press: function (oEvent) {
                                this._oScanDialog.close();
                            }.bind(this)
                        }),
                        afterOpen: function () {
                            this._initQuagga(this.getView().byId("scanContainer").getDomRef()).done(function () {
                                // Initialisation done, start Quagga
                                Quagga.start();
                            }).fail(function (oError) {
                                // Failed to initialise, show message and close dialog...this should not happen as we have
                                // already checked for camera device ni /model/models.js and hidden the scan button if none detected
                                MessageBox.error(oError.message.length ? oError.message : ("Failed to initialise Quagga with reason code " + oError.name), {
                                    onClose: function () {
                                        this._oScanDialog.close();
                                    }.bind(this)
                                });
                            }.bind(this));
                        }.bind(this),
                        afterClose: function () {
                            // Dialog closed, stop Quagga
                            Quagga.stop();
                        }
                    });

                    this.getView().addDependent(this._oScanDialog);
                }

                this._oScanDialog.open();
            },

            _initQuagga: function (oTarget) {
                var oDeferred = jQuery.Deferred();

                // Initialise Quagga plugin - see https://serratus.github.io/quaggaJS/#configobject for details
                Quagga.init({
                    inputStream: {
                        type: "LiveStream",
                        target: oTarget,
                        constraints: {
                            width: { min: 640 },
                            height: { min: 480 },
                            facingMode: "environment"
                        }
                    },
                    locator: {
                        patchSize: "medium",
                        halfSample: true
                    },
                    numOfWorkers: 2,
                    frequency: 10,
                    decoder: {
                        readers: [{
                            format: "code_128_reader",
                            config: {}
                        }]
                    },
                    locate: true
                }, function (error) {
                    if (error) {
                        oDeferred.reject(error);
                    } else {
                        oDeferred.resolve();
                    }
                });

                if (!this._oQuaggaEventHandlersAttached) {
                    // Attach event handlers...

                    Quagga.onProcessed(function (result) {
                        var drawingCtx = Quagga.canvas.ctx.overlay,
                            drawingCanvas = Quagga.canvas.dom.overlay;

                        if (result) {
                            // The following will attempt to draw boxes around detected barcodes
                            if (result.boxes) {
                                drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
                                result.boxes.filter(function (box) {
                                    return box !== result.box;
                                }).forEach(function (box) {
                                    Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
                                });
                            }

                            if (result.box) {
                                Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
                            }

                            if (result.codeResult && result.codeResult.code) {
                                Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
                            }
                        }
                    }.bind(this));

                    Quagga.onDetected(function (result) {
                        // Barcode has been detected, value will be in result.codeResult.code. If requierd, validations can be done 
                        // on result.codeResult.code to ensure the correct format/type of barcode value has been picked up

                        // Set barcode value in input field
                        this.getView().byId("scannedValue").setValue(result.codeResult.code);

                        // Close dialog
                        this._oScanDialog.close();
                    }.bind(this));

                    // Set flag so that event handlers are only attached once...
                    this._oQuaggaEventHandlersAttached = true;
                }

                return oDeferred.promise();
            }

 

This is it for the coding. Once you are done save all the files (if not autosaved) and open a terminal.
Make sure to change the directory to your project folder and type:

npm run start

This will start your application and open it in a new window so that you can test it. If it won’t open in a new window you might need to open it manually.

On startup the app should ask for camera access, you need to allow it. Otherwise the scan button will not be visible. After that it should look like below:

Via the Scan-Button you will open a context for scanning, which holds your camera view.
If you copied the code snippet given above, make sure to test it with a Code128-Barcode like the following:

 

Sample%20Code128-Barcode

Sample Code128-Barcode

 

2. Deploy app on Subaccount

 

To deploy an app to a Subaccount you need to log in to Cloud Foundry and select the right Cloud Foundry Organization and Space. You can do that by opening a terminal and type:

cf login

You will be prompted to enter your email & password for BTP authentication. After that you need to select the Org of your subaccount and a space, if more than one is available.

 

Next, you can build your project for deployment by right-clicking the mta.yaml file and selecting Build MTA Project.

This will take a moment and will create the MTA archive that is necessary for deployment on BTP.
As a final step right-click the mtar file within the newly created mta_archives folder and select Deploy MTA Archive.



This might take some time, but after it’s done you should be able to see your application deployed on your Subaccount in the HTML5 Applications tab:

You can open and test it by clicking the application name.

 

3. Integrate HTML5 apps to your launchpad

 

In this step you will have to refresh the HTML5 content provider within the Site Manager to add your newly created HTML5 app to your content there.

After that you will need to add the app to a catalog, role and group.
You can follow this blogpost by Murali Shanmugham which briefly shows the steps of integrating HTML5 apps to your launchpad site.

 

4. Open the launchpad site within SAP Mobile Start app

 

To access your site within the SAP Mobile Start app you need to access the QR code in the site settings. (SAP Mobile Start Application)

Once onboarded on your mobile device, you should see your newly created app as a tile. When you open it, it should look like that:

Screenshot%20of%20the%20app%20in%20SAP%20Mobile%20Start

Screenshot of the app in SAP Mobile Start

 

Note:  Persist camera access in Mobile Start Safari View Controller

You might have realized, that the popup for camera access comes up only the first time in the browser. After that your setting is persisted and your browser won’t ask for this again. When accessing your app via SAP Mobile Start, you will be asked for camera access every time by default. If necessary, it’s possible to persist the setting in the Safari View Controller. Therefore, you need to click the aA Icon in the top of the Shell and navigate to Website Settings. Next, for Camera select Allow.

 

5. Wrap Up

 

In this blog I covered the creation and deployment of a very simple barcode scanning custom-SAP UI5 app, that can also be launched from SAP Mobile Start.

Thank you for following this blog till the end. I hope you can make use of the information in your own implementation and use SAP Mobile Start as the native entry point. If you have any feedback feel free to share them below!

We look forward to your comments.

Stay up to date with latest news and post your questions or feedback about SAP Mobile Start in the Q&A area. Start by visiting your SAP Mobile Experience community page and click “follow”. We’ll be publishing more informative blog posts.

Want to be notified? Check your profile settings to ensure you have your settings activated.

Assigned tags

      3 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Nils Lutz
      Nils Lutz

      Hi  Dennis,

       

      ty for this blog. Everythings works except the SAP Mobile Start access. I was able to onboard my smartphone but i dont see any applications in the app. Do know you what could causing this? I see the UI5 app if i open the Launchpad on a desktop browser.

       

      Any help appreciated 🙂

       

      Best regards,

      Nils

      Author's profile photo Dennis Koehler
      Dennis Koehler
      Blog Post Author

      Hey Nils,

      thank you for your comment and for trying to get SAP Mobile Start running! 🙂

      Based on your description i'm pretty sure you were early enough to encounter a bug that is already under investigation. The "device type filtering" for apps coming from the HTML5 repository currently has still an issue. (A fix for that will arrive early October 2021)

      To make it work immediately I could provide you with a workaround:

      • Access the configuration of your app within the Content Manger
      • On the top right you should see the option to "Create a Local Copy".
      • Once a copy is created access it's configuration in the content manager and go to the Visualization-tab.
      • Make sure to uncheck/check the checkbox for mobile and tablet in the "Supported Devices" section (That should fix the filtering issue for the moment)
      • Don't forget to add the local copy to your Group / Role as well

      After a refresh you should be able to see the app within SAP Mobile Start as well! 🙂
      Hope that works for you as well as for me!

      Best regards,
      Dennis

      Author's profile photo Nils Lutz
      Nils Lutz

      Wonderful, works like a charm 🙂

      Looking forward for that fix and ty for that fast reply!

      Best regards,

      Nils