†でおきしブログ†

ウナギ食べたいヽ(•̀ω•́ )ゝ✧

【cordova】phonegap-plugin-barcodescannerへQRコードの文字コードエンコーディング機能追加しようとしたら単純ではなかった【Zxing(ZebraCrossing)】

☆TL;DR

pluginを改造する。

とりあえずAndroid側を改造。

BarcodeScanner.javaのscanメソッドに下記のコードを追加して、文字コードを設定できるように改造した。

if (obj.has("character")) {
intentScan.putExtra(Intents.Scan.CHARACTER_SET, obj.optString("character"));
}

Androidは上記対応で文字コード変換が可能である事を確認。

しかし、iOS/Windowsはそうはいかない。


☆はじめに

github.com
googleさんのzxing(zebra crossing)ライブラリを用いたcordova plugin。

カメラを使って1次元/2次元バーコードの読み取りが出来るのですが、
QRコード文字コード変換に対応していません。
f:id:deokisikun:20190421034017p:plain:w100
githubのexampleコードを元にサンプルアプリを作ってiOS/Android/Windowsで試した所、
いずれもshift-jisとutf-8は自動で文字コード変換がされますが、他はダメっぽかったです。

読み取り対象の文字コードを指定してエンコードする機能が大抵のバーコードスキャンライブラリにはあるのですが、
こちらのpluginにはありません。

☆調査

iOS/Android/Windowsで同じ挙動だった事から、それぞれのネイティブ実装は同様と想定。
Androidソースコードは見やすそうだったので、Androidを対象に調査を実施。

★手がかりを推測

Android側のPluginのソースコードBarcodeScanner.javaとなっている。

こちらのソースコードのscanメソッドの中で、何やら"intentScan.putExtra"というメソッドを使用してインテント(CaptureActivity.class)にパラメータを複数追加しており、JavaScript側からリクエストしたパラメータが設定されている事がわかる。

推測:このパラメータに文字コードを設定できないか?

★その先はzxing(zebra crossing)ライブラリ

バーコードスキャン処理の中枢はzxingライブラリの"CaptureActivity.class"が該当する事がわかる。
pluginの中に、Androidのzxingライブラリのソースコードは見当たらないので、githubのMasterリポジトリをクローン(ダウンロード)する。

https://github.com/zxing/zxing

★Intents.Scanを調査

BarcodeScanner.javaインテントにパラメータをセットする際にキーが定義されていた。

intentScan.putExtra(Intents.Scan.CAMERA_ID1, 〜

"Intents.Scan"に定義されている事がわかる。
この中に文字コード設定するようなキーがあるかもしれないと思い調査。

/**
* @see com.google.zxing.DecodeHintType#CHARACTER_SET
*/
public static final String CHARACTER_SET = "CHARACTER_SET";

zxing/Intents.java at master · zxing/zxing · GitHub

あった!


この時点で冒頭の対応(TL;DR)を取り敢えず試してみても良いのだけれど、確信するためにもう少しコードを追っていった。



android/src/com/google/zxing/client/android/CaptureActivity.java

727 handler = new CaptureActivityHandler(this, decodeFormats, decodeHints, characterSet, cameraManager);

CaptureActivityHandlerに引数でcharacterSetを渡している。

android/src/com/google/zxing/client/android/CaptureActivityHandler.java

61 CaptureActivityHandler(CaptureActivity activity,
62 Collection decodeFormats,
63 Map baseHints,
64 String characterSet,
65 CameraManager cameraManager) {

67 decodeThread = new DecodeThread(activity, decodeFormats, baseHints, characterSet,
68 new ViewfinderResultPointCallback(activity.getViewfinderView()));

DecodeThreadに引数でcharacterSetを渡している


android/src/com/google/zxing/client/android/DecodeThread.java

88 if (characterSet != null) {
89 hints.put(DecodeHintType.CHARACTER_SET, characterSet);
90 }

ヒントにcharacterSetを設定している?

ここまでくればほぼ確定だと思ったので、冒頭の対応(TL;DR)をしてみました。

iOS/Windowsについて

iOSはZxingライブラリを読み込みつつ、その実態はAVFoundation(iOS API)でバーコード読み取りを実現しており文字コード対応していない。

Windowsはバイナリ化されたZxingライブラリで出自が不明でソースもわからん。
バイナリ手前のWinRTのJavaScriptソースコードのヘッダには「microsoft open technologies」と記載がある。「microsoft open technologies」は解散という記事があったりするが、comドメインはまだ残っていた。ただやっぱりソースコードを見つける事ができなかった。

★結論

iOS/WindowsQRコード文字コード対応したければ

  • iOS
    • ZXingObjCで自前Plugin実装
  • Windows
    • ZXing.Netで自前Plugin実装

f:id:deokisikun:20190421042749p:plain:w100