「ZXing Android Embedded」でQRコードを気楽に使う
AndroidでQRコードの読み書きをやることになったんだけど、実は今までやったことがなかったのだ。
AndroidでのQRコード読み書き自体はもう色んな情報がネットにあふれており、Zxingを使えばいいというのはわかっていた。
でも、この手の情報は比較的初期に書かれていて、もう少し最新情報でやれないかなと調べていたらこんなものを発見。
既にいくつか使った紹介記事もあったんだけど、
Android - ZXingで、QRコードを撮れる - Qiita
Android StudioでZXingを使う。 - ちょこっと、めも。
少し違う内容が書けそうなので記事にした。
使ってみよう
環境
OS | Windows 10 pro |
Java | 1.8.0 |
Android Studio | 1.2.2 |
プロジェクトへのライブラリの追加
以下を追加するだけ。
- app/build.gradle
repositories { jcenter() } dependencies { compile 'com.journeyapps:zxing-android-embedded:3.0.2@aar' compile 'com.google.zxing:core:3.2.0' }
QRコードを生成する
QRコードの生成自体はzxingライブラリだけでもできるんだけど、ヘルパークラスが用意されているのでそれを使ってみる。
QrCodeDisplayActivity
package com.hatenablog.osa030.qrtest; import android.graphics.Bitmap; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.AndroidRuntimeException; import android.widget.ImageView; import com.google.zxing.BarcodeFormat; import com.google.zxing.WriterException; import com.journeyapps.barcodescanner.BarcodeEncoder; public class QrCodeDisplayActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_qr_code_display); String data = "http://osa030.hatenablog.com/"; int size = 500; try { BarcodeEncoder barcodeEncoder = new BarcodeEncoder(); Bitmap bitmap = barcodeEncoder.encodeBitmap(data, BarcodeFormat.QR_CODE, size, size); ImageView imageView = (ImageView) findViewById(R.id.imageView); imageView.setImageBitmap(bitmap); } catch (WriterException e) { throw new AndroidRuntimeException("Barcode Error.", e); } } }
activity_qr_code_display.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".QrCodeDisplayActivity"> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:layout_alignParentStart="true"> <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView"/> <Space android:layout_width="match_parent" android:layout_height="100dp"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView" android:layout_gravity="center"/> </LinearLayout> </RelativeLayout>
実行するとこんな感じでQRコードが表示される。
ヘルパークラスにはzxingへのヒントオプションも渡せる。
Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); BarcodeEncoder barcodeEncoder = new BarcodeEncoder(); Bitmap bitmap = barcodeEncoder.encodeBitmap(data, BarcodeFormat.QR_CODE, size, size, hints);
QRコードを読み込む
「ZXing Android Embedded」で一番助かるのはQRコード読み込む手段が用意されているところ。
- Activityを起動してQRコードを読み込む
- カスタムViewを埋め込んでQRコードを読み込む
どちらの場合もカメラの権限が必要になるのだが、ライブラリ(aar)のAndroidManifest.xmlに以下が追記されており、ビルド時にマージされるのでアプリ側のAndroidManifest.xmlに追記しなくても動作はする。はず。はずだってば。もししなかったら以下を追記。
AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.FLASHLIGHT"/>
ここで、「Activityを起動してQRコードを読み込む」はインテントの送受信だけなので公式の「Usage with IntentIntegrator」を見れば大体わかると思うので省略。ということで、自分のActivityにライブラリで提供されるカスタムViewを埋め込んだ場合のサンプルだけ。
QrCodeReadInViewActivity.java
package com.hatenablog.osa030.qrtest; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; import com.google.zxing.ResultPoint; import com.journeyapps.barcodescanner.BarcodeCallback; import com.journeyapps.barcodescanner.BarcodeResult; import com.journeyapps.barcodescanner.CompoundBarcodeView; import java.util.List; public class QrCodeReadInViewActivity extends AppCompatActivity { private CompoundBarcodeView mBarcodeView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_qr_code_read_in_view); mBarcodeView = (CompoundBarcodeView)findViewById(R.id.barcodeView); mBarcodeView.decodeSingle(new BarcodeCallback() { @Override public void barcodeResult(BarcodeResult barcodeResult) { TextView textView = (TextView)findViewById(R.id.textView); textView.setText(barcodeResult.getText()); } @Override public void possibleResultPoints(List<ResultPoint> list) {} }); } @Override public void onResume() { super.onResume(); mBarcodeView.resume(); } @Override public void onPause() { super.onPause(); mBarcodeView.pause(); } }
activity_qr_code_read_in_view.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context="com.hatenablog.osa030.qrtest.QrCodeReadInViewActivity"> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:layout_alignParentStart="true" android:id="@+id/qrReaderLayout"> <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView"/> <Space android:layout_width="match_parent" android:layout_height="100dp"/> <com.journeyapps.barcodescanner.CompoundBarcodeView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/barcodeView"/> </LinearLayout> </RelativeLayout>
実行するとこんな感じでカメラが起動してQRコードを読み取れる。
Viewを埋め込む場合はCompoundBarcodeViewクラスを使えばよい。ポイントは、ActivityのonResume()/onPause()でCompoundBarcodeViewのresume()/pause()を呼んでやるだけ。これをしないとdecodeSingle()をコールしても真っ黒な画面にしかならない。
実際には「Activityを起動してQRコードを読み込む」で起動されるCaptureActivityクラスも内部でCompoundBarcodeViewクラスを使っているんだけども、CompoundBarcodeViewへの細かいデコードオプション指定は今のところIntent経由じゃないとできない*1。
IntentIntegrator
CaptureActivity
CompoundBarcodeView
- 作者: 社団法人日本自動認識システム協会
- 出版社/メーカー: オーム社
- 発売日: 2010/05/19
- メディア: 単行本(ソフトカバー)
- クリック: 16回
- この商品を含むブログを見る
符号理論入門―数学的な基礎知識から「QRコード」の作成まで (I・O BOOKS)
- 作者: 濱屋進,第二I・O編集部
- 出版社/メーカー: 工学社
- 発売日: 2008/07
- メディア: 単行本
- クリック: 24回
- この商品を含むブログ (2件) を見る
*1:正確にはinitializeFromIntent()にIntentに詰めて渡してやればいいと思われる