☆TL;DR
pluginを改造する。
とりあえずAndroid側を改造。
- JavaScript側のscanメソッド呼び出しのパラメータに文字コードを追加
- ネイティブ側のscanメソッドでJavaScript側からリクエスされた文字コードを設定する
- BarcodeScanner.java
BarcodeScanner.javaのscanメソッドに下記のコードを追加して、文字コードを設定できるように改造した。
if (obj.has("character")) {
intentScan.putExtra(Intents.Scan.CHARACTER_SET, obj.optString("character"));
}
☆はじめに
github.com
googleさんのzxing(zebra crossing)ライブラリを用いたcordova plugin。
カメラを使って1次元/2次元バーコードの読み取りが出来るのですが、
QRコードの文字コード変換に対応していません。
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リポジトリをクローン(ダウンロード)する。
★Intents.Scanを調査
BarcodeScanner.javaでインテントにパラメータをセットする際にキーが定義されていた。
intentScan.putExtra(Intents.Scan.CAMERA_ID1, 〜
"Intents.Scan"に定義されている事がわかる。
この中に文字コード設定するようなキーがあるかもしれないと思い調査。
/**
zxing/Intents.java at master · zxing/zxing · GitHub
* @see com.google.zxing.DecodeHintType#CHARACTER_SET
*/
public static final String CHARACTER_SET = "CHARACTER_SET";
あった!
この時点で冒頭の対応(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 CollectiondecodeFormats,
63 MapbaseHints,
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)をしてみました。