Android 基于ZXing库的QRCode小测试
QR图码(全称为快速响应矩阵图码;英语:Quick Response Code)是二维条码的一种,于1994年由日本DENSO WAVE公司发明。QR来自英文Quick Response的缩写,即快速反应,因为发明者希望QR码可以让其内容快速被解码[1]。QR码使用四种标准化编码模式(数字、字母数字、字节(二进制)和汉字)来存储数据。QR码常见于日本,为目前日本最通用的二维空间条码,在中国也普遍使用[2]。QR码比较普通条码可以存储更多数据,也无需要像普通条码般在扫描时需要直线对准扫描仪。因此其应用范围已经扩展到包括产品跟踪,物品识别,文档管理,营销等方面。
以上来自*
本次的小项目用到了google在github上的开源库ZXing网址如下:
https://github.com/zxing/zxing
首先在Android Stduio上新建一个项目
然后在build.gradle中添加ZXing的依赖:
implementation 'com.journeyapps:zxing-android-embedded:3.5.0' implementation 'com.google.zxing:core:3.3.3'
然后就可以*调用ZXing库来快速实现二维码的解码和生成了
整个项目如下:
在布局中的内容 由于布局只是简单的使用图形界面将需要的控件拖入使用不细说了 具体如下:
扫描并且显示内容:
public class ScanActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.scan_activity); textView = (TextView) findViewById(R.id.textView); IntentIntegrator intentIntegrator = new IntentIntegrator(ScanActivity.this); intentIntegrator.initiateScan(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent intent){ IntentResult result = IntentIntegrator.parseActivityResult(requestCode,resultCode,intent); if(result != null){ String contents = result.getContents(); textView.setText(contents); } } }
采用了IntentIntegrator 类 这个类是在ZXing项目中的主要用来扫描解码
然后在onActivityResult中回调接收解码后的信息再显示在控件上
初始化扫描的源码:
/** * Initiates a scan, only for a certain set of barcode types, given as strings corresponding * to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants * like {@link #PRODUCT_CODE_TYPES} for example. * * @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for */ public final void initiateScan(Collection<String> desiredBarcodeFormats) { setDesiredBarcodeFormats(desiredBarcodeFormats); initiateScan(); //在这里开启相机的 }
/** * Initiates a scan for all known barcode types with the default camera. */ public final void initiateScan() { startActivityForResult(createScanIntent(), REQUEST_CODE); }
在IntentIntegrator类中还有许多细节设置在这里不多赘述
生成二维码:
public class GenerateActivity extends AppCompatActivity { private Button button; private ImageView imageView; private EditText editText; private Bitmap QRCodebitmap; String content; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.generate_activity); button = (Button)findViewById(R.id.button); imageView = (ImageView) findViewById(R.id.imageView); editText = (EditText) findViewById(R.id.ed); content = editText.getText().toString().trim(); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { content = editText.getText().toString().trim(); String QRCodePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "dearxy"; boolean saved = QRCodeUtil.createQRImage(content,300,300,null,QRCodePath); if(saved){ QRCodebitmap =getBitmapFromPath(QRCodePath); imageView.setImageBitmap(QRCodebitmap); }else { Log.e("aaaaa", "保存二维码失败"); } } }); } public Bitmap getBitmapFromPath(String path) { if (!new File(path).exists()) { System.err.println("getBitmapFromPath: file not exists"); return null; } // Bitmap bitmap = Bitmap.createBitmap(1366, 768, Config.ARGB_8888); // Canvas canvas = new Canvas(bitmap); // Movie movie = Movie.decodeFile(path); // movie.draw(canvas, 0, 0); // // return bitmap; byte[] buf = new byte[1024 * 1024];// 1M Bitmap bitmap = null; try { FileInputStream fis = new FileInputStream(path); int len = fis.read(buf, 0, buf.length); bitmap = BitmapFactory.decodeByteArray(buf, 0, len); if (bitmap == null) { System.out.println("len= " + len); System.err .println("path: " + path + " could not be decode!!!"); } } catch (Exception e) { e.printStackTrace(); } return bitmap; } }
在这里主要调用了QRCodeUtil类这个类在ZXing中没有具体给出是需要自己根据ZXing中给出的工具自己写的:
public class QRCodeUtil { /** * 生成二维码Bitmap * * @param content 内容 * @param widthPix 图片宽度 * @param heightPix 图片高度 * @param logoBm 二维码中心的Logo图标(可以为null) * @param filePath 用于存储二维码图片的文件路径 * @return 生成二维码及保存文件是否成功 */ public static boolean createQRImage(String content, int widthPix, int heightPix, Bitmap logoBm, String filePath) { try { if (content == null || "".equals(content)) { return false; } //配置参数 Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //容错级别 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); //设置空白边距的宽度 // hints.put(EncodeHintType.MARGIN, 2); //default is 4 // 图像数据转换,使用了矩阵转换 BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix, heightPix, hints); int[] pixels = new int[widthPix * heightPix]; // 下面这里按照二维码的算法,逐个生成二维码的图片, // 两个for循环是图片横列扫描的结果 for (int y = 0; y < heightPix; y++) { for (int x = 0; x < widthPix; x++) { if (bitMatrix.get(x, y)) { pixels[y * widthPix + x] = 0xff000000; } else { pixels[y * widthPix + x] = 0xffffffff; } } } // 生成二维码图片的格式,使用ARGB_8888 Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888); bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix); if (logoBm != null) { bitmap = addLogo(bitmap, logoBm); } //必须使用compress方法将bitmap保存到文件中再进行读取。直接返回的bitmap是没有任何压缩的,内存消耗巨大! return bitmap != null && bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(filePath)); } catch (WriterException | IOException e) { e.printStackTrace(); } return false; } /** * 在二维码中间添加Logo图案 */ private static Bitmap addLogo(Bitmap src, Bitmap logo) { if (src == null) { return null; } if (logo == null) { return src; } //获取图片的宽高 int srcWidth = src.getWidth(); int srcHeight = src.getHeight(); int logoWidth = logo.getWidth(); int logoHeight = logo.getHeight(); if (srcWidth == 0 || srcHeight == 0) { return null; } if (logoWidth == 0 || logoHeight == 0) { return src; } //logo大小为二维码整体大小的1/5 float scaleFactor = srcWidth * 1.0f / 5 / logoWidth; Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888); try { Canvas canvas = new Canvas(bitmap); canvas.drawBitmap(src, 0, 0, null); canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2); canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null); // canvas.save(Canvas.ALL_SAVE_FLAG); canvas.save(); // canvas.save(Canvas.ALL_SAVE_FLAG); canvas.restore(); } catch (Exception e) { bitmap = null; e.getStackTrace(); } return bitmap; }