WebServiceによる開発方法

WebServiceを使ったRayBarcodeの連続読み取り機能の開発方法を説明します。この方法で、開発者が指定したWebServiceのコールバックを呼び出すことで、カメラ画面を維持したまま連続して複数のバーコードを読み取る操作のことです。

  • 連続読み取りの間隔は、ユーザが「RayKit」アプリでSalesforceにログインした後、ナビゲーションメニューの「設定」の「連続スキャン間隔」から変更できます。開発者が変更することはできません。
  • 連続読み取りで読み取りの終了タイミングは、開発者がWebServiceで指定できます。エンドユーザーもカメラ画面の左上にある「←」をタップすることで、連続読み取りを終了させることができます。
  • 読み取ったバーコードの情報は、複数の読み取り結果を蓄積してからまとめてSalesforceに送信することも、1回の読み取りごとにSalesforceに送信することもできます。これは開発者がWebServiceで実装できます。
  • 連続読み取りを制御するWebServiceは、同じコードをVisualforceアプリとLightningアプリから共通で使用できます。
  • WebServiceの呼び出しは、Salesforce組織のAPI要求数を消費します。読み取りの成功、失敗にかかわらず1回の読み取り制御につき1消費します。Salesforce組織のAPI要求数が最大に達したとき、読み取り機能は単独読み取りの場合と同じ動作になります。

連続読み取りの画面例、読み取った個数と結果をオーバーレイ表示できる:

前提

次の知識が必要です。

  • Visualforceページの開発またはLightningページの開発
  • CSSを使った開発
  • JavaScriptを使った開発
  • Salesforce1モバイルアプリケーションの開発
  • ApexによるWebServiceの開発

利用手順

連続読み取りに対応する、バーコード読み取り画面の開発手順は次のようになります。

  1. 画面のレイアウトを決定する。最小の構成で「読み取りボタン」と「読み取り結果の表示領域」が必要。
  2. 連続読み取りを制御するWebService(Apexクラス)を作る。
  3. 読み取りが成功した後の処理をコントローラ(Apexクラス)で受ける。
  4. 作成したVisualforceページをSalesforce1のナビゲーションメニューに表示する。

連続読み取りの実際の開発例は、このページのチュートリアル5とチュートリアル6を参照してください。その後に、インタフェースを説明します。

連続読み取り機能の操作の流れ

連続読み取りでは、WebServiceで読み取りを制御するためバーコード読み取りの仕組みで説明した操作の流れとは少し異なります。以下のチャートではWebServiceは「continuousScanCallback」の部分です。

sequenceDiagram participant ユーザ participant RayKitアプリ participant Salesforce ユーザ->>RayKitアプリ: スマートフォンでアプリを起動 Salesforce->>ユーザ: Salesforceログイン画面を表示 ユーザ->>RayKitアプリ: Salesforceにログイン Salesforce->>ユーザ: Salesforce1のホーム画面を表示 ユーザ->>RayKitアプリ: Salesforce1上のページを開く ユーザ->>RayKitアプリ: 連続読み取りボタンをタップ RayKitアプリ->>ユーザ: カメラ画面を表示 ユーザ->>RayKitアプリ: カメラでバーコードを読み取り RayKitアプリ->>Salesforce: 読み取ったデータをSalesforceに渡す Salesforce-->RayKitアプリ: 読み取ったデータをcontinuousScanCallbackで判定 RayKitアプリ->>ユーザ: 判定結果を読み取り中のカメラ画面に表示 ユーザ->>RayKitアプリ: 再度の読み取り(繰り返し) RayKitアプリ->>Salesforce: 読み取ったデータをSalesforceに渡す(繰り返し) Salesforce-->RayKitアプリ: 読み取ったデータをcontinuousScanCallbackで判定 Salesforce-->RayKitアプリ: 正常な読み取りが規定数に到達した場合 Salesforce->>RayKitアプリ: onScanCompleteの処理 RayKitアプリ->>ユーザ: 連続読み取りの結果ページを表示

チュートリアル5. Visualforceアプリによる連続読み取り

Visualforceページの開発Lightningアプリケーションの開発のチュートリアルでは、1回の読み取り操作ごとに「読み取り開始」ボタンをタップする必要がありました。複数のQRコードを連続して読み取りたい場合、何度もタップするのは不便です。チュートリアル5では連続読み取りを実装します。

連続読み取りを有効にするには、gcbc:GcBarcodeScannerVFコンポーネントのcontinuousScan属性をtrueに設定します。さらにcontinuousScanCallback属性により、連続でバーコードを読み取る場合の操作を制御するコールバックを指定します。

次の手順ではPC(Mac)のブラウザで連続読み取りのアプリを作成します。

  1. Salesforce Classicの場合、「設定 > ビルド > 開発 > Apexクラス」を開く。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > プラットフォームツール > カスタムコード > Apexクラス」を開く。
  2. 読み取り結果を受け取るコントローラTutorial5Controller.clsと連続読み取りを制御するWebServiceであるTutorial5Service.clsを作成する。
// Tutorial5Controller.cls
public with sharing class Tutorial5Controller {

    public PageReference onContinuousScanCompleteAction() {        
        return null;
    }
    
    // 読み取り結果を表示する要求に対して読み取り結果を返す
    public string getContinuousScanOutputMessage() {
        string[] results = splitMultipleScanResult(this.continuousScanResult);
        
        if (results != null){
            string message = '';
            integer counter = 1;
            string[] types = this.continuousScanTypes.split(',');
            for(string result : results){
                message += counter + ')[' + types[counter - 1] +  '] ' + result + '\r\n';
                counter++;
            }
            return message;
        }
        return '';        
    }
    
    // 連続読み取りのバーコードの値を格納する
    public string continuousScanResult {get;set;}
    
    // 連続読み取りのバーコードの種類を格納する
    public string continuousScanTypes {get;set;}
    
    private static string[] splitMultipleScanResult(string scanResult) {
        if (string.isEmpty(scanResult)) {
            return null;
        }
        string[] scanResultList = scanResult.split(',');
        for (Integer i = 0; i < scanResultList.size(); i++){
            // UTF-8でURLデコードする
            scanResultList[i] = EncodingUtil.urlDecode(scanResultList[i], 'UTF-8');
        }
        return scanResultList;
    }
}

次のコードは、連続読み取りを制御するWebServiceです。このWebServiceは連続読み取り中に読み取り結果をユーザに表示するメッセージを含みます。Apexクラスとして追加します。

// Tutorial5Service.cls
@RestResource(urlMapping='/gcbc_tutorial5/*')
global with sharing class GcBarcodeScannerContinuousScanService {
    
    @HttpPost
    global static BarcodeScanResponse processBarcodeContinuousScan() {
        BarcodeScanData data = (BarcodeScanData)JSON.deserialize
            (RestContext.request.requestBody.toString(), BarcodeScanData.class);
        BarcodeScanResponse response = new BarcodeScanResponse();
        
        if (data.scannedResult == null || data.scannedType != 'QR_CODE') {
            // 読み取り結果が空の場合、またはQRコード以外のバーコードを読み取った場合

            // 現在の読み取り結果を破棄する
            response.preserveScanResult = false;

            // 開発者は、ここで読み取り履歴と現在の読み取り内容を比較し、
            // 重複がある場合に現在の読み取り内容を破棄することもできます。
            // 破棄された読み取りデータは、次回の読み取り時には履歴には含まれません。
            
            response.displayMessage = 
                '非対応のバーコード形式[' + data.scannedType + ']です。QRコードを読み取ってください。';
            response.notifyErrorFeedback = true;
        } else {
            // 読み取り結果がQRコードの場合
            response.preserveScanResult = true;
            // 現在の読み取り回数を返す
            integer count = 1;
            if (data.preservedScannedContent != null) {
                count = data.preservedScannedContent.size() + 1;
            }
            response.displayMessage = '読み取り済み: ' + count + ' / 5、現在の読み取り結果:' + data.scannedResult;
        }
        
        // 5回のQRコードの読み取りが完了した後、読み取りを終了する
        if (
            data.preservedScannedContent != null && 
            data.preservedScannedContent.size() >= 4 && 
            response.preserveScanResult) {
            response.shouldContinueScan = false;
        }
        else {
            response.shouldContinueScan = true;
        }
        
        return response;         
    }
    
    global class BarcodeScanData{
        // 読み取ったすべてのバーコードの値
        @testVisible string[] preservedScannedContent;
        // 読み取ったすべてのバーコードの種類
        @testVisible string[] preservedScannedType;
        // 現在読み取ったバーコードの値
        @testVisible string scannedResult;
        // 現在読み取ったバーコードの種類
        @testVisible string scannedType;     
    }
    
    global class BarcodeScanResponse {
        boolean preserveScanResult;
        string displayMessage;
        boolean shouldContinueScan;
        boolean notifyErrorFeedback;

        public BarcodeScanResponse() {
            // 読み取り結果をpreservedScannedContentとpreservedScannedTypeに蓄積しない
            this.preserveScanResult = false;
            // 連続読み取り時に読み取り画面に表示するメッセージを初期化
            this.displayMessage = '';
            // 連続読み取りを継続する
            this.shouldContinueScan = true;
            // 読み取りエラー時にビープ音を再生しない
            this.notifyErrorFeedback = false;
        }        
    }
}

次に読み取り開始画面を作成します。この画面は、連続読み取りの完了後に結果をすべて表示する画面も兼ねています。

以下の手順ではPC(Mac)のブラウザで「連続読み取り開始」ボタンを置く画面となるVisualforceページ Tutorial5.vfp を作成します。この画面は「連続読み取り開始」ボタンと「読み取り結果の表示領域」を持ちます。

  1. Salesforce Classicの場合、「設定 > ビルド > 開発 > Apexクラス」を開く。Lightning Experienceの場合、歯車アイコンをクリックした後「設定 > プラットフォームツール > カスタムコード > Apexクラス」を開く。
  2. 後述の「Tutorial5.vfp」を貼り付ける。
  3. Visualforceページの「Lightning Experience、Salesforce1、Lightning コミュニティで利用可能」をチェックをオンにする。
  4. 「プレビュー」をクリックする。
  5. 「読み取り開始」ボタンが表示されるが、PC(Mac)のブラウザではクリックできない。
<!-- RayBarcode バーコード読み取り サンプルコード -->
<!-- Tutorial5.vfp -->
<apex:page controller="Tutorial3Controller">
    <!-- Lightning Design Systemを有効にする -->
    <apex:slds />
    <!-- 見出しを表示する -->
    <apex:sectionHeader title="チュートリアル3"/>
    <!-- 読み取りボタンを表示する -->
    <gcbc:GcBarcodeScannerVF
        id="continuousScanButton"
        buttonText="連続読み取り開始"
        continuousScan="true"
        continuousScanCallback="gcbc_tutorial5"
        onScanComplete="{!onContinuousScanCompleteAction}"
        reRender="allScansOutput"
        scanResults="{!ContinuousScanResult}" 
        scannedTypes="{!ContinuousScanTypes}"
        styleClass="slds-button slds-button--brand slds-m-top--medium" 
        style="width:200px;" />
    <!-- 結果の表示領域 -->    
    <apex:outputPanel id="allScansOutput" layout="block">
        {!ContinuousScanOutputMessage}        
    </apex:outputPanel>
    <script type="text/javascript">
        (function(){
            var id = "{!$Component.continuousScanButton}";
            var scannerDom = document.getElementById(id);
            scannerDom.addEventListener('scansuccess', (e)=>{        
                console.log(e.detail);                
                // 次のコードは、Apexへのデフォルトのアクションコールバックを防ぎます。
                //e.preventDefault();
            });            
        })();
    </script>
</apex:page>

RayKitアプリでSalesforceにログインし、Salesforce1ナビゲーションメニューから「チュートリアル5」をタップして動作を確認します。次の5つのバーコードのうち、はじめの3つはQRコードです。残りは、JAN13(EAN13)とITFです。QRコードを5回読み取れるので、上から順に読み取って、4番目と5番目でエラーになります。1~3番目を再度読み取って5回の連続読み取り操作を完了します。

チュートリアル6. Lightningアプリによる連続読み取り

連続読み取りに対応するには、次の作業が必要です。

  • continuousScan属性の値を「true」に設定する。
  • 連続と見取りの動作を制御するためのWebServiceを実装する。サンプルパッケージがインストールされている場合、「gcbc_continuousscandemo」サンプルを使用できる。
  • 複数の読み取り結果を処理する。

次のサンプルはgcbc:GcBarcodeScannerLTで連続読み取りに対応する例です。

<aura:component implements="flexipage:availableForAllPageTypes" access="global">
    <aura:attribute name="continuousScanResult" type="String" />
    <aura:attribute name="continuousScannedTypes" type="String" />    
    <aura:attribute name="continuousScanResultOutout" type="String" />  
            
    <h1>連続読み取りを実行する</h1>
    <br />    
    <gcbc:GcBarcodeScannerLT
        aura:id="continuous-scan-button" 
        buttonText="連続読み取り"
        scanResults="{!v.continuousScanResult}"
        scannedTypes="{!v.continuousScannedTypes}"
        onScanComplete="{!c.onContinuousScanComplete}"
        continuousScan="true"
        continuousScanCallback="gcbc_tutorial5"
        />
    <br />
    <ui:outputText value="{!v.continuousScanResultOutout}" />
</aura:component>

サンプルに対して定義されたonContinuousScanCompleteメソッドは、次のようになります。

({
    onContinuousScanComplete: function (component, event, helper) {
        var result = event.getParam("success");
        if (result){
            var data = component.get("v.continuousScanResult");
            var types = component.get("v.continuousScannedTypes").split(",");
            var records = data.split(",");
            for(var i = 0; i < records.length; i++){
                records[i] = '[' + types[i] + '] ' + decodeURIComponent(records[i]);
            }
            component.set("v.continuousScanResultOutout", records.join("\r\n"));
        }else{
            alert("読み取り失敗");
        }
    }
})

「RayKit」アプリでSalesforceにログインし、Salesforce1ナビゲーションメニューから「チュートリアル6」をタップして動作を確認します。

continuousScanCallback属性のWebService

continuousScanCallback属性のWebServiceのリクエスト本体は、次のようなコードでBarcodeScanDataに変換できる文字列になります。

(BarcodeScanData)JSON.deserialize(RestContext.request.requestBody.toString(), BarcodeScanData.class);

コールバックの応答は BarcodeResponseScan オブジェクトとなります。ジョブを実行するメソッドは、 processBarcodeContinuousScan という名前にする必要がありますprocessBarcodeContinuousScan の定義は次のようになります。

global static BarcodeScanResponse processBarcodeContinuousScan()

BarcodeScanResponseクラスの属性

連続読み取りの動作の制御で使用するデータです。

属性名 属性型 説明
displayMessage String 読み取り画面に表示されるメッセージの文字列。
notifyErrorFeedback Boolean エラーのフィードバックの有無を指定します。trueのときデバイスでビープ音を再生します。falseのときビープ音を再生しません。実際にビープ音が再生されるかどうかは、スマートフォンの設定により異なります。たとえばマナーモードに設定されている場合、再生されない場合があります。
preserveScanResult Boolean trueは現在の読み取りが成功したことを示し、それ以外の場合はfalseを示します。 読み取りが成功すると、現在の読み取り結果が履歴データ(BarcodeScanData.preservedScannedContent、BarcodeScanData.preservedScannedType)に保存されます。
shouldContinueScan Boolean trueは、別の読み取りを続行することを示し、それ以外の場合はfalseを示します。

BarcodeScanDataクラスの属性

コールバックで使用するデータフォーマットです。

属性名 属性型 説明
preservedScannedContent String[] 保存されているすべての読み取りデータの内容を示します。
preservedScannedType String[] 保存されたすべての読み取りされたバーコードの種類のリストを示します。バーコードの種類の値は、読み取ったバーコードの種類を参照してください。
scannedResult String 現在の読み取り結果を示します。
scannedType String 現在の読み取ったバーコードの種類を示します。
Copyright © 2019 GrapeCity inc. All rights reserved.