Goal
You want to create an S10 application with which the user can scan codes (barcodes, QR codes, etc.). The recognized data from the code should be processed further automatically.

Mobile devices offer a number of new application possibilities through access to the camera, sensors and so on. There are JavaScript libraries for scanning barcodes, which you can easily integrate and use.



Implementation
As a rule, the JavaScript library that implements the scanning of barcodes is integrated into the HTML code in a specific S10 view. In the following example we use the HTML5 QR Code scanner , which we include with the following line:

    <!-- Open-source library for scanning barcodes/qrcodes -->
    <!--  https://github.com/mebjas/html5-qrcode -->
    <script src='../../../scripts/html5-qrcode.min.js'> </script>

First a new object is created and the scanner is started. It also defines what should happen when the scanner has successfully recognized a code. In this case, the recognized text is placed in an input field. This can be an S10 InputField, which means that the content of the variable is then also available in the ABAP class.

    // Start the scanner
    var html5QrcodeScanner = new Html5QrcodeScanner(
        "reader", { fps: 10, qrbox: 250 });
    html5QrcodeScanner.render(onScanSuccess);

    // The scanner recognized a code
    function onScanSuccess(decodedText, decodedResult) {

        // Put the recognized text of the code in an input field
        document.getElementById('scan_result').value = decodedText;

        // Needed to synchronize the data
        S10Enter();
    }


The further processing of the data can take place in different ways:

1. The recognized data from the code are only displayed to the user and not processed further
2. The data is processed automatically by a JavaScript method, e.g. dividing it into individual fields from a total text
3. Processing takes place in an ABAP method.

<!-- Target area for the scanner-->
<div style="width:100%;height:35%;" id="reader"></div>

<!-- Normal S10 input field-->
<input class="input" id="scan_result" name="scan_result" type="text">

<!-- Hidden s10 field triggering JavaScript method on value change-->
<input class="input" name="scan_result" type="hidden"
   onchange="parse_scan_result(this.value);">

<!-- Hidden s10 field triggering ABAP method on value change-->
<input class="input" name="scan_result" type="hidden"
onchange="S10Apply('parse_scan_result'); ">

Example: Posting goods issue
With this S10 application, a user can use his mobile device to scan a QR code that contains the following data:
Document number of a delivery, material number, position in the delivery and delivery quantity.
If a code is recognized and the data is read in, he can then post the goods issue directly trigger in the SAP system.



ABAP program: /S10/BARCODE_EXAMPLE

program /s10/barcode_example.

class barcode_class definition inheriting from /s10/any.

  public section.

* project path (textpool, screens)
    constants:
        projectpath type string value 'sap/bc/bsp/s10/barcode'.

    data:
      vbeln type vbkok-vbeln,
      posnr type vbpok-posnr_vl,
      lfimg type vbpok-lfimg,
      matnr type mara-matnr,
      maktx type makt-maktx.

    methods:

* Method to book outgoing goods
      update_delivery,

* Build the description for a material
      build_maktx
        importing
          matnr type mara-matnr
        exporting
          maktx type makt-maktx.

endclass.

class barcode_class implementation.

  method build_maktx.

* read maktx
    select single maktx from makt into maktx
            where matnr = matnr and spras = sy-langu.
  endmethod.

  method update_delivery.

* Use a self defined authority object
    authority-check object 'Z_S10_BARC'
      id 'ACTVT' field '10'.

* not authorized -> message to user and stop processing
    if sy-subrc <> 0.
      s10errormessage(
         exporting
          msgid             =     'CACSIB'
          msgno             =      503
      ).
    endif.

    data: ps_vbkok type vbkok.
    data: lw_vbpok type vbpok.
    data: pt_vbpok type table of vbpok.
    data: lt_prot type table of prott.
    data: lw_prot type  prott.

    clear ps_vbkok.

    ps_vbkok-vbeln_vl        = vbeln.
    ps_vbkok-vbtyp_vl        = 'J'.
    ps_vbkok-wabuc         = 'X'.
    ps_vbkok-wadat_ist     = sy-datum.

    lw_vbpok-vbeln_vl  = vbeln.
    lw_vbpok-posnr_vl  = posnr.
    lw_vbpok-lfimg       = lfimg.
    lw_vbpok-umvkz    = 1.
    lw_vbpok-umvkn    = 1.
    append lw_vbpok to pt_vbpok. clear lw_vbpok.

    call function 'WS_DELIVERY_UPDATE_2'
      exporting
        vbkok_wa               = ps_vbkok
        synchron               = 'X'
        commit                 = 'X'
        delivery               = vbeln
        if_error_messages_send = 'X'
      tables
        vbpok_tab              = pt_vbpok
        prot                   = lt_prot
      exceptions
        error_message          = 4
        others                 = 2.

    if sy-subrc = 0.

      s10infomessage( s10localize( id = 'booking_success' ) ).

    endif.

* Error occured
    if sy-subrc <> 0.

      s10errormessage(
        exporting
          msgid             =     sy-msgid
          msgno             =    sy-msgno
      ).

    endif.

* Error messages ?
    loop at lt_prot into lw_prot where msgty = 'E' or msgty = 'A'.

      data: msgno type syst_msgno.
      msgno = lw_prot-msgno.

      s10errormessage(
       exporting
         msgid             =     lw_prot-msgid
         msgno             =   msgno
           ).

    endloop.
  endmethod.
  
endclass.

* main class for this application
class main definition inheriting from /s10/any.

  public section.

    data:   mybarcode_class type ref to barcode_class.

    methods:
      logon.

endclass.


class main implementation.

* logon user
  method logon.

* set S10 license
    s10setlicense( 'Synactive GmbH demo license number=100 role=s10demo_role 
maxusers=10 signature=821.126.87.7'
). * create manager object create object mybarcode_class. * start list display mybarcode_class->s10nextscreen( 'start'). endmethod. endclass.

The HTML view: barcode_class.start.html

<!DOCTYPE html>
<html>

<head>
    <!-- Default header for S10 applications-->
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=400">
    <link rel='stylesheet' type='text/css' href='../../../style/s10.style.css'>
    <link rel='stylesheet' type='text/css' href='../../../style/custom.style.css'>
    <script src='../../synactiveS10/synactiveS10.java.js'></script>

    <!-- Open-source library for scanning barcodes/qrcodes -->
          https://github.com/mebjas/html5-qrcode -->
    <script src='../../../scripts/html5-qrcode.min.js'></script>

    <!-- Open source library for generating barcodes/qrcodes   -->
    <script src='../../../scripts/qrcode_generator.js'></script>

    <title>Warenausgang buchen</title>

</head>


<body style="width: 100%; margin: 0px; padding: 0px;" onload='init();' class="colorscheme9">

    <div class="headerarea" style="width: 100%; padding: 10px;">
        <b>Warenausgang buchen</b>
    </div>

    <!-- Toolbar definition with navigation-->
    <div class="toolbar">

        <button id="new_scan_button" type="button" class="toolbarbutton" onclick="new_scan()">
            Neuer Scan
        </button>

        <button type="button" class="toolbarbutton" style="float: right;" onclick="S10Logoff();">
            Abmelden
        </button>

    </div>

    <!-- Tabs definition-->
    <table class="tabstrip">
        <tr>
            <td id="scan" class="tabactive" onclick="S10ActivateTab(this);">
                Scannen
            </td>
            <td id="generate" class="tab" onclick="S10ActivateTab(this);">
                QR-Code generieren
            </td>
    </table>

    <!-- Area for tab 1 (scan) -->
    <div class="tabpageactive" id="scan.area">

        <div style="width:100%;height:35%;" id="reader"></div>

        <table id="confirmation_area"
            style="display:none;width: 100%; padding: 15px; 
            border-radius: 12px; background: #f1f5fb;">
            <tr>
                <td>
                    <div>
                        <span style="font-weight:bold">Kontrolle</span>
                    </div>
                </td>
            </tr>
            <tr>
                <td>
                    <label class="label" for="vbeln">Belegnummer</label><br>
                    <span class="output" name="vbeln"></span>
                    <input class="input" id="vbeln" name="vbeln" type="hidden">
                    <br>

                    <label class="label" for="matnr">Material</label><br>
                    <span class="output" name="matnr"></span>
                    <span class="output" name="maktx"></span>
                    <input class="input" id="matnr" name="matnr" type="hidden">
                    <br>

                    <label class="label" for="posnr">Position</label><br>
                    <span class="output" name="posnr"></span>
                    <input class="input" id="posnr" name="posnr" type="hidden">
                    <br>

                    <label class="label" for="lfimg">Menge</label><br>
                    <span class="output" name="lfimg"></span>
                    <input class="input" id="lfimg" name="lfimg" type="hidden">
                    <br>
                    <br>
                    <button style="margin:0px;width:100%;border-radius:3px;height:75px;" 
                            type="button" class="button"
                        onclick="S10Apply('update_delivery');">
                        Warenausgang buchen
                    </button>

                </td>
            </tr>
        </table>
    </div>

    <!-- Area for tab 2 (generate) -->
    <div class="tabpage" id="generate.area">

        <table style="width: 100%; padding: 15px; 
                    border-radius: 12px; background: #f1f5fb;">

            <tr>
                <td style="width:220px;">
                    <label class="label" for="vbeln_in">Belegnummer</label><br>
                    <input class="input" id="vbeln_in" type="text">
                    <br>

                    <label class="label" for="matnr_in">Material</label><br>
                    <input class="input" id="matnr_in" type="text">
                    <br>

                    <label class="label" for="posnr_in">Position</label><br>
                    <input class="input" id="posnr_in" type="text">
                    <br>

                    <label class="label" for="lfimg_in">Menge</label><br>
                    <input class="input" id="lfimg_in" type="text">
                    <br>
                    <br>

                    <button style="margin:0px;width:100%;border-radius:3px;height:75px;" 
                            type="button" class="button"
                        onclick="make_qr_code();">
                        QR-Code generieren
                    </button>
                </td>

                <td style="vertical-align:top;">
                    <input syle="width:100%;" type="text" class="output" id="qrode_text_input"> </input>
                    <div id="generated_qrcode" style="width:150px; height:15px; margin-top:5px;"></div>

                </td>
            </tr>
        </table>
    </div>

    <script>

        // The scanner recognized a code
        function onScanSuccess(decodedText, decodedResult) {

            // Handle on success condition with the decoded text or result.
            var a = decodedText.split(";"), i;

            // Parse the text of the scanned code and put
            // the values in inputfield 
            for (i = 0; i < a.length; i++) {
                var key = a[i].split(":")[0];
                var val = a[i].split(":")[1];

                if (document.getElementById(key) != null) {
                    document.getElementById(key).value = val;
                }
            }

            html5QrcodeScanner.clear();
            // ^ this will stop the scanner (video feed) and clear the scan area.

            // Make the area with the results visible
            document.getElementById("confirmation_area").style.display = "inline-block";

            S10Enter();
        }

        // Start the scanner
        var html5QrcodeScanner = new Html5QrcodeScanner(
            "reader", { fps: 10, qrbox: 250 });
        html5QrcodeScanner.render(onScanSuccess);

        // Start a new scanner
        function new_scan() {

            document.getElementById("confirmation_area").style.display = "none";

            html5QrcodeScanner = new Html5QrcodeScanner(
                "reader", { fps: 10, qrbox: 250 });
            html5QrcodeScanner.render(onScanSuccess);
        }

        var qrcode = new QRCode(document.getElementById("generated_qrcode"), {
            width: 100,
            height: 100
        });

        // Generate a new QR code according to the values in inputfields        
        function make_qr_code() {

            var text = "";
            text += "vbeln:" + document.getElementById("vbeln_in").value + ";";
            text += "matnr:" + document.getElementById("matnr_in").value + ";";
            text += "posnr:" + document.getElementById("posnr_in").value + ";";
            text += "lfimg:" + document.getElementById("lfimg_in").value;

            document.getElementById("qrode_text_input").value = text;
            qrcode.makeCode(text);
        }

    </script>
</body>

</html>

Component: S10 Framework