head_hexagonはにらぼ☆てっくtale_hexagon

Androidでバーコードリーダーを実装する

Posted by nagashima on 2017/05/30 under Development | Be the First to Comment


こんにちは、nagashimaです。今回はAndroidのお話をします。

今作っているアプリにバーコードリーダーの機能を入れる必要がありライブラリを調べました。
やりたいことは次の3つ
・1次元/2次元バーコードが読める
・画面上のボタン操作でライトのON/OFFができる
・バーコードの読み込みは画面中央部の指定エリアのみ

まず出てきたのがZXingです。zxing-android-embeddedという拡張ライブラリを使うことで簡単にバーコードを読むことができます。

build.gradleにcompile ‘com.journeyapps:zxing-android-embedded:3.4.0’を追加して

IntentIntegrator integrator = new IntentIntegrator(this);
integrator.initiateScan();

で呼び出すことでスキャン画面を呼び出すことができます。
バーコードの解析結果はonActivityResultで取得します。

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
    if (scanResult != null) {
        Log.d(TAG, scanResult.getContents());
    }
}

IntentIntegratorに各種セッターがあるのでカメラの設定も簡単にできました。

ただ問題が…。ZXingの1次元バーコードの読み取りは方向固定なので、バーコードが縦になっていると読めないみたいです。

他のライブラリを探しているとGoogle Play serviceに含まれているという記事を見かけ調べてみました。
サンプルも公開されているので、これを見つつ実装。

build.gradleにcompile ‘com.google.android.gms:play-services-vision:10.2.0’を追加して

BarcodeDetector barcodeDetector = new BarcodeDetector
        .Builder(this)
        .build();
barcodeDetector.setProcessor(new Detector.Processor() {
    @Override
    public void release() {

}
    @Override
    public void receiveDetections(Detector.Detections detections) {
        if (detections.getDetectedItems().size() != 0) {
            for(int i = 0; i< detections.getDetectedItems().size(); i++){
                Barcode barcode = detections.getDetectedItems().valueAt(i);
                Log.d(TAG,barcode.displayValue);
            }
        }
}
});

CameraSource cameraSource = new CameraSource
        .Builder(getApplicationContext(), barcodeDetector)
        .build();

surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        cameraSource.start(surfaceView.getHolder());
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        cameraSource.stop();
        cameraSource.release();
}
});

バーコードの解析結果を受け取る”BarcodeDetector”とカメラをラップした”CameraSource”を、SurfaceViewと紐付けるだけなのですが、CameraSourceが曲者でした。

AndroidでライトはCameraの機能の一部なので、Cameraの操作が必要なのですが、CameraSourceにはライトを操作するような関数が用意されてなく…。サンプルをよく調べるとCameraSourceを自前で持っていて、そこでライトのON/OFFの制御をしていたようです。なので同じように自前でCameraSourceを作りそこでライトを操作するようにしました。そのうちvisionのCameraSourceにもこのあたりが追加されるのでしょうかね?

コメントを残す