OutSystemsモバイル(2) カメラ

ForgeにあるOutSystemsのスマートフォンアプリ対応機能OutSystems Nowを利用して、スマートフォンのネイティブ機能を試してみます。

今回は、カメラです。Nowについてはきちんとした仕様が見つからないので、試してみた結果のみで書いている点に注意してください。

シリーズ一覧:

機能

OutSystems Now内で、TakePictureというWeb Blockとして実装されています。

OutSystems Now App(スマートフォンアプリ。スマートフォンのアプリストアから無料でダウンロードできます)で開いているときのみ、以下の動作をします。

  1. ButtonIdで指定したボタン(またはリンク)がクリックされたとき、スマートフォンのカメラアプリを起動
  2. ユーザが撮影
  3. OutSystems Now Appに戻り、結果がInputIdで指定したInput内に文字列として設定される
  4. Inputのchangeイベント(JavaScript)を発生させる

Inputに設定される時に文字列になっているのは、写真のバイナリがBase64エンコーディングされているからです。

このBase64エンコードされた文字列を、JavaScript(クライアントサイド)かOutSystemsのBinaryData.Base64ToBinary Action(サーバサイド)で元のバイナリに戻せます。

利用手順(サンプル実装の仕様)

まず、Picture Attribute(Binary型)と、PictureFileName Attribute(Text型)を持つEntityを用意しておきます(Member Entity)。

それぞれ、撮影した写真の実体を格納する列、写真に付ける名前を格納する列です。

動作確認のためにスクリーンを作ります。

WebScreen仕様

  1. 撮影した結果を表示するImage。データベースから表示するのでいったんEntityに保存する必要があります
  2. これがカメラ機能本体のWeb Block。
  3. クリックするとカメラを起動します
  4. 撮影完了後Base64エンコードした結果を格納します

利用手順

仕様に従ってEntityを作っておいてください。

次にWeb Screenを作って仕様通りに以下の部品を配置します。プロパティ設定値も書いておきます。

TakePictureはボタンかリンクと、結果を格納するInputが必要です。

1:Image(標準部品)

  • Name:Photo
  • Image:AgilePlatform(デフォルト表示する画像です。適当でいいと思います)
  • Cache:NoCache
  • Type:Database(データベースに格納したBinary型を画像として表示する)
  • FileName:MemberForm.Record.Member.PictureFileName(フォームに紐づけをsたレコードのどの属性がファイル名を示すか)
  • Attribute:Member.Picture(データベース内の画像を入れたバイナリ型属性)
  • Entity Identifier:MemberForm.Record.Member.PictureFileName

2:TakePicture(InterfaceレイヤのOutSystemsNow/DeviceFeatures/TakePictureをスクリーンにドロップ)

  • ButtonId:btnPicture.Id(クリックしたらカメラを起動するボタンのId)
  • InputId:inputPicture.Id(撮影後、Base64エンコードした撮影結果の文字列を格納するInputのId)

3:Button(標準部品)

  • Name:btnPicture
  • Label:”カメラを起動”
  • Destination:Common\ExternalURL
  • URL:”#”(カメラ起動用なので余計な遷移を起こさないようにする)

4:Input(標準部品)

  • Name:inputPicture
  • Variable:Var1(Text型の変数。撮影結果のBase64エンコード後の値を格納する変数として指定)
  • Extended Properties: onchange

onchangeの値として以下のJavaScript関数定義を設定します。

画像のsrc属性にInputの値をBase64でコードした値を設定する処理です。

“$(‘#” + Photo.Id + “‘).attr(‘src’, ‘data:image/jpeg;base64,’ + $(‘#” + inputPicture.Id + “‘).val());”

なんでこんな処理をするかというと、更新前にプレビューしたいからです。Imageがデータベースから表示する設定なので、データベースに格納されていないバイナリはOutSystemsの枠組みではうまく表示できませんでした。なのでしかたなくJavaScriptで片づけています。

プレビューがいらなければ、InputのOnChangeでScreen Actionを呼んで、BinaryData.Base64ToBinary した結果をImageに紐づけているレコードのバイナリ型に設定しておけば、保存してページを読み直せばきちんと表示できます。

これが撮影した直後の画面です。写真の下の変な文字列がBase64エンコード結果。

JavaScriptのonchangeでバイナリに戻して画像のsrcに設定しているのですぐに写真が見られています。

カメラで撮影したスクリーン(Now)

気になる点

TakePicture WebBlock内で、カメラ起動時のパラメータ(たぶん画像の幅など)が固定値埋め込みになっています。

もともと指定できないような値であれば仕方ないですが、部品としてはパラメータに出しておいてほしいところですが……

function OutSystemsNative_TakePicture(destinationInput) {    
    if ((window.OutSystemsNowWindowsVersion != 'undefined' && window.OutSystemsNowWindowsVersion )){ // windows version
        // Windows OS API
        // {"plugin_name" : "TakePicture", 
        //  "plugin_params": "{ quality: 60,  destinationType : Camera.DestinationType.DATA_URL, encodingType: Camera.EncodingType.JPEG, targetWidth: 600, targetHeight: 600, correctOrientation: true }"
        //  "success_action" : "OutSystemsNative_OnPictureSuccessWindows", 
        //  "success_params" : "{ 'destinationInput' : 'id', 'imageData': base64data}"
        //  "error_action" : "OutSystemsNative_OnPictureSuccessFailWindows"
        //  "error_params" : "{message : null}"
        
        OutSystemsNative_WindowsNotify("TakePicture", 
            '{ "quality": 60,  "destinationType" : "Camera.DestinationType.DATA_URL", "encodingType": "Camera.EncodingType.JPEG", "targetWidth": 600, "targetHeight": 600, "correctOrientation": true }', 
                "OutSystemsNative_OnPictureSuccessWindows", 
                '{ "destinationInput" : "' + destinationInput.attr('id') + '", "imageData": null}', 
                "OutSystemsNative_OnPictureSuccessFailWindows", 
                '{"message": null}');
        
    } else{    
        if(!navigator.camera) {
            console.log('navigator.camera not defined');
        } else {
            navigator.camera.getPicture(OutSystemsNative_OnPictureSuccess.bind(null, destinationInput), OutSystemsNative_OnPictureFail, { quality: 60,  destinationType : Camera.DestinationType.DATA_URL, encodingType: Camera.EncodingType.JPEG, targetWidth: 600, targetHeight: 600, correctOrientation: true });
        }
    }    
}

関連情報

公式チュートリアル

シェアする

  • このエントリーをはてなブックマークに追加

フォローする