一.介绍
Zxing是一个开放的源码,用java实现的多种样式的1D/2D条码处理库,它包含了联系到其他语言的端口。Zxing可以实现手机的内置摄像头完成条码的扫描及解码。目前支持:UPC-A ,UPC-E ,EAN-8 ,EAN-13 ,39 码,93码。
二.Zxing库的主要类
1.CaptureActivity :启动Activity,也就是扫描器
2.CaptureActivityHandler :解码处理器,负责调用另外的线程进行解码
3.DecodeThread :解码线程
4.com.google.zxing.client.android.camera包:摄像头调用包
5.ViewfinderView :自定义的View,就是我们看到的拍摄中间的框框
三. 使用Zxing生成二维码
//Edited by mythou//
//要转换的地址或字符串,可以是中文 public void createQRImage(String url) { try { //判断URL合法性 if (url == null || "".equals(url) || url.length() < 1) { return; } Hashtablehints = new Hashtable (); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //图像数据转换,使用了矩阵转换 BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints); int[] pixels = new int[QR_WIDTH * QR_HEIGHT]; //下面这里按照二维码的算法,逐个生成二维码的图片, //两个for循环是图片横列扫描的结果 for (int y = 0; y < QR_HEIGHT; y++) { for (int x = 0; x < QR_WIDTH; x++) { if (bitMatrix.get(x, y)) { pixels[y * QR_WIDTH + x] = 0xff000000; } else { pixels[y * QR_WIDTH + x] = 0xffffffff; } } } //生成二维码图片的格式,使用ARGB_8888 Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888); bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT); //显示到一个ImageView上面 sweepIV.setImageBitmap(bitmap); } catch (WriterException e) { e.printStackTrace(); } } 上面就是二维码生成的方法接口,如果你只是使用者方法,很简单,只要传一个URL即可。或者像现在一些移动的App推广,把App下载地址转成二维码; 上面代码做的事情不多,主要是调用Zxing库里面的QRCodeWriter().encode的方法对我们传进去的URL进行编码 四.扫描二维码获取信息 扫描获取二维码信息工作稍微复杂一点,主要是需要编写的Camera的使用,这个跟我们一般使用的Camera一样,需要使用Sufaceview作为预览; 获取二维码数据的关键在于处理说在Camera的自动对焦回函数那里,调用ZXing的解码接口:
//Edited by mythou//
private void restartPreviewAndDecode() { if (state == State.SUCCESS) { state = State.PREVIEW; CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode); CameraManager.get().requestAutoFocus(this, R.id.auto_focus); activity.drawViewfinder(); } }
由于解码需要一点时间,所以ZXing的解码调用,都是使用Handler作为线程通讯机制,解码的工作都是放在独立线程里面使用的,如果你放在主线程解码,恐怕ANR问题是避免不了
public void handleMessage(Message message) { switch (message.what) { case R.id.auto_focus: //Log.d(TAG, "Got auto-focus message"); // When one auto focus pass finishes, start another. This is the closest thing to // continuous AF. It does seem to hunt a bit, but I'm not sure what else to do. if (state == State.PREVIEW) { CameraManager.get().requestAutoFocus(this, R.id.auto_focus); } break; case R.id.restart_preview: Log.d(TAG, "Got restart preview message"); restartPreviewAndDecode(); break; case R.id.decode_succeeded: //解码成功,获取到界面的结果和原来的二维码数据 Log.d(TAG, "Got decode succeeded message"); state = State.SUCCESS; Bundle bundle = message.getData(); Bitmap barcode = bundle == null ? null : (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP); activity.handleDecode((Result) message.obj, barcode); break; case R.id.decode_failed: // We're decoding as fast as possible, so when one decode fails, start another. state = State.PREVIEW; CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode); break; case R.id.return_scan_result: Log.d(TAG, "Got return scan result message"); activity.setResult(Activity.RESULT_OK, (Intent) message.obj); activity.finish(); break; case R.id.launch_product_query: Log.d(TAG, "Got product query message"); String url = (String) message.obj; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); activity.startActivity(intent); break; } }