参考网上文章,做如下实践。
implementation('com.journeyapps:zxing-android-embedded:3.6.0') { transitive = false } implementation 'com.google.zxing:core:3.3.0'
第一步:获取根据场景获取bitmap
1、通过url获取bitmap:
private void urlToBitmap(final String pic) { new Thread() { @Override public void run() { try { URL url = new URL(pic); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); if (conn.getResponseCode() == 200) { InputStream inputStream = conn.getInputStream(); Bitmap bitmap = BitmapFactory.decodeStream(inputStream); //decodeImage(bitmap); } } catch (Exception e) { e.printStackTrace(); } } }.start(); }
2、通过base64获取bitmap:
public static Bitmap base64ToBitmap(String base64Data) { byte[] bytes = Base64.decode(base64Data, Base64.DEFAULT); return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); }
第二步:解析Bitmap,获取二维码对应的url。
public static Result handleQRCodeFormBitmap(Bitmap bitmap) { Result result = null; if (bitmap != null) { // getSmallerBitmap 非常重要,图片太大会OOM,太小会找不到 bitmap = BitmapUtil.getSmallerBitmap(bitmap); // 获取bitmap的宽高,像素矩阵 int width = bitmap.getWidth(); int height = bitmap.getHeight(); int[] pixels = new int[width * height]; bitmap.getPixels(pixels, 0, width, 0, 0, width, height); // 最新的库中,RGBLuminanceSource 的构造器参数不只是bitmap了 RGBLuminanceSource source = new RGBLuminanceSource(width, height, pixels); BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source)); Reader reader = new MultiFormatReader(); // 尝试解析此bitmap,!!注意!! 这个部分一定写到外层的try之中,因为只有在bitmap获取到之后才能解析。写外部可能会有异步的问题。(开始解析时bitmap为空) try { Map<DecodeHintType, Object> hints = new HashMap<>(); hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);//花更多的时间用于寻找图上的编码,优化准确性,但不优化速度,Boolean类型 //加了hints解决了部分二维码解析出纯数字非url的问题 result = reader.decode(binaryBitmap, hints); } catch (NotFoundException e) { e.printStackTrace(); } catch (ChecksumException e) { e.printStackTrace(); } catch (FormatException e) { e.printStackTrace(); } } return result; }
//传入一个 bitmap,判断其大小是否 是 某一个 阙值(我在这里设置了1500000)的倍数。如果是其倍数,那么就等比缩小(也即是当 目前的bitmap大小为1500000的4倍的时候,那么宽,高各缩小2倍) // 注意:阈值不能过小,图片压缩过小会导致识别不到二维码。 public static Bitmap getSmallerBitmap(Bitmap bitmap) { int size = bitmap.getWidth() * bitmap.getHeight() / 1500000;//目前设计上最大的尺寸1000*1500,可根据自身产品情况做调整。 if (size <= 1) return bitmap; // 如果小于 else { Matrix matrix = new Matrix(); matrix.postScale((float) (1 / Math.sqrt(size)), (float) (1 / Math.sqrt(size))); Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); return resizeBitmap; } }
第三步:result不为null,那么操作栏增加“识别图中二维码”的选项;用户点击该选项后,执行webview的访问操作:url=result.getText();
/** * 判断是否为二维码 * param url 图片地址 * return */ private void decodeImage(final Bitmap bitmap) { new Thread() { @Override public void run() { result = handleQRCodeFormBitmap(bitmap); Logger.d("result:" + result); if (result == null) { isQR = false; } else { isQR = true; Logger.d("result text:" + result.getText()); } if (isQR) { handler.sendEmptyMessage(0);//通知用户操作ui修改 } } }.start(); }