少し前の記事で「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のパーミッションが必要なはずなんだけど、こっちで書かなくても使える……
ライブラリ側で吸収してくれてるのかな。不思議な感じ。
最初に「一応メモ」とは書いたものの、読み込みの精度は充分だと思うし、すごく簡単に実装できてすごい。
現場からは以上です!