少し前の記事で「Mobile Vision APIやる」って書いたばかりだけど、少し前の案件で使ったので、一応メモ。
リンク
Android用のZxingライブラリ
https://github.com/journeyapps/zxing-android-embedded
QRコード生成の参考はこちら
http://qiita.com/alingogo/items/3006e5685057c23db6bd
build.gradle
android {
// 追加
repositories {
jcenter()
}
}
dependencies {
// appcompatの23以上が必要
compile 'com.android.support:appcompat-v7:23.1.0'
// 追加
compile 'com.journeyapps:zxing-android-embedded:3.4.0'
}
あと、buildToolsVersionは 23.0.2 以上
Activity
QrActivity.java
public class QrActivity extends AppCompatActivity {
private static final String TAG = QrActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qr);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
if (result.getContents() == null) {
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
// EditTextにQRコードの内容をセット
EditText et = (EditText) findViewById(R.id.et);
et.setText(result.getContents());
et.setSelection(et.getText().length());
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_capture: // キャプチャ画面起動
IntentIntegrator integrator = new IntentIntegrator(this);
// Fragmentで呼び出す場合
// IntentIntegrator integrator = IntentIntegrator.forFragment(this);
// 独自でキャプチャ画面のActivityを作成
// integrator.setCaptureActivity(ToolbarCaptureActivity.class);
// → QrToolbarCaptureActivityのSample: https://github.com/journeyapps/zxing-android-embedded/blob/master/sample/src/main/java/example/zxing/ToolbarCaptureActivity.java
// スキャンするバーコード形式を指定
// integrator.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES);
// キャプチャ画面の下方にメッセージを表示
integrator.setPrompt("Scan a barcode");
// カメラの特定(この場合はフロントカメラを使用)
// integrator.setCameraId(Camera.CameraInfo.CAMERA_FACING_FRONT);
// 読み取り時の音声をオフに
integrator.setBeepEnabled(false);
// バーコードを画像保存できるっぽい(保存先はonActivityResultでIntentResult#getBarcodeImagePath()で取得)
integrator.setBarcodeImageEnabled(true);
// スキャン画面の回転の制御
integrator.setOrientationLocked(true);
// キャプチャ画面起動
integrator.initiateScan();
break;
case R.id.create_qr: // QRコード生成
Bitmap bitmap;
try {
EditText et = (EditText) findViewById(R.id.et);
String text = et.getText().toString();
if (text.equals("")) {
return;
}
bitmap = createQRCodeByZxing(et.getText().toString(), 480);
ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setImageBitmap(bitmap);
} catch (WriterException e) {
Log.e(TAG, "WriterException", e);
return;
}
break;
}
}
// ここそのまま→ http://qiita.com/alingogo/items/3006e5685057c23db6bd
// ありがとうございます。
public Bitmap createQRCodeByZxing(String contents, int size) throws WriterException {
//QRコードをエンコードするクラス
QRCodeWriter writer = new QRCodeWriter();
//異なる型の値を入れるためgenericは使えない
Hashtable encodeHint = new Hashtable();
//日本語を扱うためにシフトJISを指定
encodeHint.put(EncodeHintType.CHARACTER_SET, "shiftjis");
//エラー修復レベルを指定
//L 7%が復元可能
//M 15%が復元可能
//Q 25%が復元可能
//H 30%が復元可能
encodeHint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
BitMatrix qrCodeData = writer.encode(contents, BarcodeFormat.QR_CODE, size, size, encodeHint);
//QRコードのbitmap画像を作成
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.argb(255, 255, 255, 255)); //いらないかも
for (int x = 0; x < qrCodeData.getWidth(); x++) {
for (int y = 0; y < qrCodeData.getHeight(); y++) {
if (qrCodeData.get(x, y) == true) {
//0はBlack
bitmap.setPixel(x, y, Color.argb(255, 0, 0, 0));
} else {
//-1はWhite
bitmap.setPixel(x, y, Color.argb(255, 255, 255, 255));
}
}
}
return bitmap;
}
}
res/layout/activity_qr.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".activity.QrActivity">
<Button
android:id="@+id/start_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/mg_m"
android:onClick="onClick"
android:text="@string/qr_start_capture"/>
<EditText
android:id="@+id/et"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/mg_m"
android:hint="@string/qr_result"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/border"/>
<Button
android:id="@+id/create_qr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/mg_m"
android:onClick="onClick"
android:text="@string/qr_create"/>
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/mg_m"
android:contentDescription="QRコード"/>
</LinearLayout>
AndroidManifest.xml
ライブラリ内のキャプチャ画面をセット
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="fullSensor"
tools:replace="screenOrientation"/>
独自のActivityも入れることができます。その辺はGithubのサンプルを参考に。
あと、CAMERAとFLASHLIGHTのパーミッションが必要なはずなんだけど、こっちで書かなくても使える……
ライブラリ側で吸収してくれてるのかな。不思議な感じ。
最初に「一応メモ」とは書いたものの、読み込みの精度は充分だと思うし、すごく簡単に実装できてすごい。
現場からは以上です!

