亲宝软件园·资讯

展开

android zxing扫码 Android集成zxing扫码框架功能

Legned24 人气:0

       我们知道zxing是一个强大的处理二维码和条形码等的开源库,本篇文章记录一下自己在项目中集成zxing开源库的过程。

导入依赖

implementation 'com.google.zxing:core:3.3.3'

申请权限

       在AndroidManifest中申请相应权限:

<!--相机-->
<uses-permission android:name="android.permission.CAMERA" />
<!--震动-->
<uses-permission android:name="android.permission.VIBRATE" />
<!--存储-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

导入相关代码和资源文件

       导入的代码文件如下(源码在末尾):

      相关的资源文件:

      1、在res/values下新建ids.xml文件,引入下面id:

<!--二维码/条形码扫描相关-->
<item name="auto_focus" type="id" />
<item name="decode" type="id" />
<item name="decode_failed" type="id" />
<item name="decode_succeeded" type="id" />
<item name="encode_failed" type="id" />
<item name="encode_succeeded" type="id" />
<item name="launch_product_query" type="id" />
<item name="quit" type="id" />
<item name="restart_preview" type="id" />
<item name="return_scan_result" type="id" />
<item name="search_book_contents_failed" type="id" />
<item name="search_book_contents_succeeded" type="id" />

      2、在res/values下新建attrs.xml文件,加入扫码框的属性,主要是ViewfinderView在使用:

<!--扫码框属性-->
<declare-styleable name="ViewfinderView">
 <attr name="corner_color" format="color" />
 <attr name="corner_size" format="dimension" />
 <attr name="corner_stroke_width" format="dimension" />
 <attr name="corner_position" format="enum">
  <enum name="inside" value="1" />
  <enum name="outside" value="2" />
 </attr>
 <attr name="line_color" format="color" />
 <attr name="line_height" format="dimension" />
 <attr name="line_move_distance" format="dimension" />
 <attr name="frame_width" format="dimension" />
 <attr name="frame_height" format="dimension" />
 <attr name="frame_centerX" format="dimension" />
 <attr name="frame_centerY" format="dimension" />
 <attr name="frame_color" format="color" />
 <attr name="frame_stroke_width" format="dimension" />
 <attr name="mask_color" format="color" />
 <attr name="result_point_color" format="color" />
 <attr name="label_text" format="string" />
 <attr name="label_text_color" format="color" />
 <attr name="label_text_size" format="dimension" />
 <attr name="label_text_margin" format="dimension" />
</declare-styleable>

       3、在res下新建raw目录,导入beep.mp3,实现扫码成功的滴滴音效,BeepManager在使用

       上面是一些比较重要的资源。

       然后介绍一下几个主要的类:

       1、ViewfinderView:自定义扫描框,代码如下,因为有注释,就不多说明了。

public final class ViewfinderView extends View {
 private static final long ANIMATION_DELAY = 10L;
 private static final int OPAQUE = 1;
 private static final int CORNER_INSIDE = 1; //四个边角在扫描区内
 private static final int CORNER_OUTSIDE = 2; //四个边角在扫描区外
 private Paint paint;
 //扫描区四个边角的颜色
 private int cornerColor;
 //扫描区边角的大小
 private float cornerSize;
 //扫描区边角的宽度
 private float cornerStrokeWidth;
 //边角的方向,在扫描区域内还是扫描区域外
 private int cornerPosition;
 //扫描线颜色
 private int lineColor;
 //扫描线高度
 private float lineHeight;
 //扫描线移动距离
 private float lineMoveDistance;
 //扫描区域宽度度
 private float frameWidth;
 //扫描区域高度
 private float frameHeight;
 //扫描区域中心位置的X坐标,默认正中间,在onLayout中设置
 private float frameCenterX;
 //扫描区域中心位置的Y坐标,默认正中间,在onLayout中设置
 private float frameCenterY;
 //扫描区域边框颜色
 private int frameColor;
 //扫描区域边框宽度
 private float frameStrokeWidth;
 //模糊区域颜色
 private int maskColor;
 //扫描点的颜色
 private int resultPointColor;
 //扫描区域提示文本
 private String labelText;
 //扫描区域提示文本颜色
 private int labelTextColor;
 //扫描区域提示文本字体大小
 private float labelTextSize;
 //扫描区域提示文本的边距
 private float labelTextMargin;
 public static int scannerStart = 0;
 public static int scannerEnd = 0;
 private Collection<ResultPoint> possibleResultPoints;
 private Collection<ResultPoint> lastPossibleResultPoints;
 // This constructor is used when the class is built from an XML resource.
 public ViewfinderView(Context context, AttributeSet attrs) {
  super(context, attrs);
  //初始化自定义属性信息
  TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewfinderView);
  cornerColor = ta.getColor(R.styleable.ViewfinderView_corner_color, getResources().getColor(R.color.colorPrimary));
  cornerSize = ta.getDimension(R.styleable.ViewfinderView_corner_size, dp2px(context, 28));
  cornerStrokeWidth = ta.getDimension(R.styleable.ViewfinderView_corner_stroke_width, dp2px(context, 4));
  cornerPosition = ta.getInt(R.styleable.ViewfinderView_corner_position, CORNER_INSIDE);
  lineColor = ta.getColor(R.styleable.ViewfinderView_line_color, getResources().getColor(R.color.colorPrimary));
  lineHeight = ta.getDimension(R.styleable.ViewfinderView_line_height, dp2px(context, 3));
  lineMoveDistance = ta.getDimension(R.styleable.ViewfinderView_line_move_distance, dp2px(context, 2));
  frameWidth = ta.getDimension(R.styleable.ViewfinderView_frame_width, dp2px(context, 220));
  frameHeight = ta.getDimension(R.styleable.ViewfinderView_frame_height, dp2px(context, 220));
  frameCenterX = ta.getDimension(R.styleable.ViewfinderView_frame_centerX, -1);
  frameCenterY = ta.getDimension(R.styleable.ViewfinderView_frame_centerY, -1);
  frameColor = ta.getColor(R.styleable.ViewfinderView_frame_color, Color.parseColor("#90FFFFFF"));
  frameStrokeWidth = ta.getDimension(R.styleable.ViewfinderView_frame_stroke_width, dp2px(context, 0.2f));
  maskColor = ta.getColor(R.styleable.ViewfinderView_mask_color, Color.parseColor("#60000000"));
  resultPointColor = ta.getColor(R.styleable.ViewfinderView_result_point_color, Color.TRANSPARENT);
  labelText = ta.getString(R.styleable.ViewfinderView_label_text);
  labelTextColor = ta.getColor(R.styleable.ViewfinderView_label_text_color, Color.WHITE);
  labelTextSize = ta.getDimension(R.styleable.ViewfinderView_label_text_size, sp2px(context, 15));
  labelTextMargin = ta.getDimension(R.styleable.ViewfinderView_label_text_margin, dp2px(context, 18));
  ta.recycle();
  paint = new Paint();
  paint.setAntiAlias(true);
  possibleResultPoints = new HashSet<ResultPoint>(5);
 }
 @Override
 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  super.onLayout(changed, left, top, right, bottom);
  //如果没有设置frameCenterX和frameCenterY默认布局正中间的X、Y坐标
  frameCenterX = (frameCenterX == -1) ? getWidth() / 2f : frameCenterX;
  frameCenterY = (frameCenterY == -1) ? getHeight() / 2f : frameCenterY;
  //设置扫描区域位置
  int leftOffset = (int) (frameCenterX - frameWidth / 2f);
  int topOffset = (int) (frameCenterY - frameHeight / 2f);
  //设置扫描区不超过屏幕
  leftOffset = leftOffset > 0 ? leftOffset : 0;
  topOffset = topOffset > 0 ? topOffset : 0;
  Rect rect = new Rect();
  rect.left = leftOffset;
  rect.top = topOffset;
  rect.right = (int) (leftOffset + frameWidth);
  rect.bottom = (int) (topOffset + frameHeight);
  CameraManager.get().setFramingRect(rect);
 }
 @Override
 public void onDraw(Canvas canvas) {
  Rect frame = CameraManager.get().getFramingRect();
  if (frame == null) {
   return;
  }
  if (scannerStart == 0 || scannerEnd == 0) {
   scannerStart = frame.top;
   scannerEnd = frame.bottom;
  }
  int width = canvas.getWidth();
  int height = canvas.getHeight();
  //绘制模糊区域
  drawExterior(canvas, frame, width, height);
  //绘制扫描区边框
  drawFrame(canvas, frame);
  //绘制边角
  drawCorner(canvas, frame);
  //绘制提示信息
  drawTextInfo(canvas, frame);
  //绘制扫描线
  drawScanLine(canvas, frame);
  //绘制闪烁点
  drawResultPoint(canvas, frame);
  // Request another update at the animation interval, but only repaint the laser line,
  // not the entire viewfinder mask.
  //指定重绘区域,该方法会在子线程中执行
  postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);
 }
 // 绘制模糊区域 Draw the exterior (i.e. outside the framing rect) darkened
 private void drawExterior(Canvas canvas, Rect frame, int width, int height) {
  paint.setColor(maskColor);
  canvas.drawRect(0, 0, width, frame.top, paint);
  canvas.drawRect(0, frame.top, frame.left, frame.bottom, paint);
  canvas.drawRect(frame.right, frame.top, width, frame.bottom, paint);
  canvas.drawRect(0, frame.bottom, width, height, paint);
 }
 // 绘制扫描区边框 Draw a two pixel solid black border inside the framing rect
 private void drawFrame(Canvas canvas, Rect frame) {
  if (frameStrokeWidth > 0) {
   paint.setColor(frameColor);
   if (cornerPosition == CORNER_INSIDE) { //边角在扫描区内
    //左边
    canvas.drawRect(frame.left, frame.top, frame.left + frameStrokeWidth, frame.bottom, paint);
    //上边
    canvas.drawRect(frame.left, frame.top, frame.right, frame.top + frameStrokeWidth, paint);
    //右边
    canvas.drawRect(frame.right - frameStrokeWidth, frame.top, frame.right, frame.bottom, paint);
    //下边
    canvas.drawRect(frame.left, frame.bottom - frameStrokeWidth, frame.right, frame.bottom, paint);
   } else { //边角在扫描区外
    //左边
    canvas.drawRect(frame.left - frameStrokeWidth, frame.top - frameStrokeWidth,
      frame.left, frame.bottom + frameStrokeWidth, paint);
    //上边
    canvas.drawRect(frame.left - frameStrokeWidth, frame.top - frameStrokeWidth,
      frame.right + frameStrokeWidth, frame.top, paint);
    //右边
    canvas.drawRect(frame.right, frame.top - frameStrokeWidth, frame.right + frameStrokeWidth,
      frame.bottom + frameStrokeWidth, paint);
    //下边
    canvas.drawRect(frame.left - frameStrokeWidth, frame.bottom, frame.right + frameStrokeWidth,
      frame.bottom + frameStrokeWidth, paint);
   }
  }
 }
 //绘制边角
 private void drawCorner(Canvas canvas, Rect frame) {
  if (cornerSize > 0 && cornerStrokeWidth > 0) {
   paint.setColor(cornerColor);
   if (cornerPosition == CORNER_INSIDE) { //绘制在扫描区域内区
    //左上
    canvas.drawRect(frame.left, frame.top, frame.left + cornerSize, frame.top + cornerStrokeWidth, paint);
    canvas.drawRect(frame.left, frame.top, frame.left + cornerStrokeWidth, frame.top + cornerSize, paint);
    //右上
    canvas.drawRect(frame.right - cornerSize, frame.top, frame.right, frame.top + cornerStrokeWidth, paint);
    canvas.drawRect(frame.right - cornerStrokeWidth, frame.top, frame.right, frame.top + cornerSize, paint);
    //左下
    canvas.drawRect(frame.left, frame.bottom - cornerSize, frame.left + cornerStrokeWidth, frame.bottom, paint);
    canvas.drawRect(frame.left, frame.bottom - cornerStrokeWidth, frame.left + cornerSize, frame.bottom, paint);
    //右下
    canvas.drawRect(frame.right - cornerSize, frame.bottom - cornerStrokeWidth, frame.right, frame.bottom, paint);
    canvas.drawRect(frame.right - cornerStrokeWidth, frame.bottom - cornerSize, frame.right, frame.bottom, paint);
   } else { //绘制在扫描区域外区
    //左上
    canvas.drawRect(frame.left - cornerStrokeWidth, frame.top - cornerStrokeWidth,
      frame.left - cornerStrokeWidth + cornerSize, frame.top, paint);
    canvas.drawRect(frame.left - cornerStrokeWidth, frame.top - cornerStrokeWidth,
      frame.left, frame.top - cornerStrokeWidth + cornerSize, paint);
    //右上
    canvas.drawRect(frame.right + cornerStrokeWidth - cornerSize, frame.top - cornerStrokeWidth,
      frame.right + cornerStrokeWidth, frame.top, paint);
    canvas.drawRect(frame.right, frame.top - cornerStrokeWidth,
      frame.right + cornerStrokeWidth, frame.top - cornerStrokeWidth + cornerSize, paint);
    //左下
    canvas.drawRect(frame.left - cornerStrokeWidth, frame.bottom, frame.left - cornerStrokeWidth + cornerSize,
      frame.bottom + cornerStrokeWidth, paint);
    canvas.drawRect(frame.left - cornerStrokeWidth, frame.bottom + cornerStrokeWidth - cornerSize,
      frame.left, frame.bottom + cornerStrokeWidth, paint);
    //右下
    canvas.drawRect(frame.right + cornerStrokeWidth - cornerSize, frame.bottom,
      frame.right + cornerStrokeWidth, frame.bottom + cornerStrokeWidth, paint);
    canvas.drawRect(frame.right, frame.bottom + cornerStrokeWidth - cornerSize,
      frame.right + cornerStrokeWidth, frame.bottom + cornerStrokeWidth, paint);
   }
  }
 }
 //绘制文本
 private void drawTextInfo(Canvas canvas, Rect frame) {
  if (!TextUtils.isEmpty(labelText)) {
   paint.setColor(labelTextColor);
   paint.setTextSize(labelTextSize);
   paint.setTextAlign(Paint.Align.CENTER);
   Paint.FontMetrics fm = paint.getFontMetrics();
   float baseY = frame.bottom + labelTextMargin - fm.ascent;
   canvas.drawText(labelText, frame.left + frame.width() / 2, baseY, paint);
  }
 }
 //绘制扫描线
 private void drawScanLine(Canvas canvas, Rect frame) {
  if (lineHeight > 0) {
   paint.setColor(lineColor);
   RadialGradient radialGradient = new RadialGradient(
     (float) (frame.left + frame.width() / 2),
     (float) (scannerStart + lineHeight / 2),
     360f,
     lineColor,
     shadeColor(lineColor),
     Shader.TileMode.MIRROR);
   paint.setShader(radialGradient);
   if (scannerStart <= scannerEnd) {
    //椭圆
    RectF rectF = new RectF(frame.left + 2 * lineHeight, scannerStart, frame.right - 2 * lineHeight,
      scannerStart + lineHeight);
    canvas.drawOval(rectF, paint);
    scannerStart += lineMoveDistance;
   } else {
    scannerStart = frame.top;
   }
   paint.setShader(null);
  }
 }
 private void drawResultPoint(Canvas canvas, Rect frame) {
  if (resultPointColor != Color.TRANSPARENT) {
   Collection<ResultPoint> currentPossible = possibleResultPoints;
   Collection<ResultPoint> currentLast = lastPossibleResultPoints;
   if (currentPossible.isEmpty()) {
    lastPossibleResultPoints = null;
   } else {
    possibleResultPoints = new HashSet<ResultPoint>(5);
    lastPossibleResultPoints = currentPossible;
    paint.setAlpha(OPAQUE);
    paint.setColor(resultPointColor);
    for (ResultPoint point : currentPossible) {
     canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
    }
   }
   if (currentLast != null) {
    paint.setAlpha(OPAQUE / 2);
    paint.setColor(resultPointColor);
    for (ResultPoint point : currentLast) {
     canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);
    }
   }
  }
 }
 //处理颜色模糊
 public int shadeColor(int color) {
  String hax = Integer.toHexString(color);
  String result = "20" + hax.substring(2);
  return Integer.valueOf(result, 16);
 }
 public void drawViewfinder() {
  invalidate();
 }
 public void addPossibleResultPoint(ResultPoint point) {
  possibleResultPoints.add(point);
 }
 private int dp2px(Context context, float dpValue) {
  float density = context.getApplicationContext().getResources().getDisplayMetrics().density;
  return (int) (dpValue * density + 0.5f);
 }
 private int sp2px(Context context, float spValue) {
  float scaleDensity = context.getApplicationContext().getResources().getDisplayMetrics().scaledDensity;
  return (int) (spValue * scaleDensity + 0.5f);
 }
}

       2、CaptureActivity:扫码的Activity基类,代码如下;

/**
 * Created by xuzhb on 2019/11/16
 * Desc:扫码的Activity类
 * 整个Activity最重要的两个控件是一个SurfaceView(摄像头)和一个ViewfinderView(扫描区)
 * 对于继承CaptureActivity的Activity子类来说,
 * 可以选择在自己的布局中定义和CaptureActivity的布局文件id相同的控件,
 * 这样即使它们在两个布局中表现不同也能执行相同的逻辑,包括其他控件
 * 或者选择重写getSurfaceView()和getViewfinderView()返回对应的两个控件,
 * 扫码最终是在handleDecode(Result result, Bitmap bitmap)处理扫描后的结果
 */
public class CaptureActivity extends AppCompatActivity implements SurfaceHolder.Callback {
 private static final String TAG = "CaptureActivity";
 private static final int IMAGE_PICKER = 1999;
 private BeepManager mBeepManager;
 private CaptureActivityHandler mHandler;
 private Vector<BarcodeFormat> mDecodeFormats;
 private String mCharacterSet;
 private InactivityTimer mInactivityTimer;
 private boolean hasSurface = false;
 private boolean isLightOn = false; //是否打开闪光灯
 private boolean isPlayBeep = true; //是否开启扫描后的滴滴声
 private boolean isVibrate = true; //是否震动
 private String mPhotoPath;   //选中的图片路径
 private TitleBar mTitleBar;
 private SurfaceView mSurfaceView;
 private ViewfinderView mViewfinderView;
 private LinearLayout mLightLl;
 private ImageView mLightIv;
 private TextView mLightTv;
 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(getLayoutId());
  CameraManager.init(getApplicationContext());
  mBeepManager = new BeepManager(this);
  hasSurface = false;
  mInactivityTimer = new InactivityTimer(this);
  handleView(savedInstanceState);
  initView();
  initListener();
 }
 protected int getLayoutId() {
  return R.layout.activity_capture;
 }
 protected void handleView(@Nullable Bundle savedInstanceState) {
 }
 private void initView() {
  mTitleBar = findViewById(R.id.title_bar);
  mSurfaceView = findViewById(R.id.surfaceView);
  mViewfinderView = findViewById(R.id.viewfinderView);
  mLightLl = findViewById(R.id.light_ll);
  mLightIv = findViewById(R.id.light_iv);
  mLightTv = findViewById(R.id.light_tv);
 }
 protected void initListener() {
  //因为继承CaptureActivity的Activity子类的布局不一定包含id为title_bar和light_ll的控件,
  //没有的话如果子类通过super.initListener()覆写时会因为找不到而报异常,所以这里加了一个判空;
  //如果子类的布局中包含id相同的控件,则不需要在子类中再重写相同的逻辑
  if (mTitleBar != null) {
   StatusBarUtil.INSTANCE.darkModeAndPadding(this, mTitleBar, Color.BLACK, 0, false);
   mTitleBar.setOnLeftClickListener(v -> {
    finish();
    return null;
   });
   mTitleBar.setOnRightClickListener(v -> {
    openAlbum(); //打开相册选取图片扫描
    return null;
   });
  }
  if (mLightLl != null) {
   mLightLl.setOnClickListener(v -> switchLight()); //打开或关闭闪光灯
  }
 }
 //打开相册
 protected void openAlbum() {
  Intent intent = new Intent(Intent.ACTION_PICK, null);
  intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
  startActivityForResult(intent, IMAGE_PICKER);
 }
 //开启/关闭闪光灯
 private void switchLight() {
  if (CameraManager.get() != null) {
   if (isLightOn) {
    mLightTv.setText("轻触点亮");
    CameraManager.get().turnLightOffFlashLight();
   } else {
    mLightTv.setText("轻触关闭");
    CameraManager.get().turnOnFlashLight();
   }
   isLightOn = !isLightOn;
   mLightIv.setSelected(isLightOn);
  }
 }
 @Override
 protected void onResume() {
  super.onResume();
  SurfaceHolder holder = getSurfaceView().getHolder();
  if (hasSurface) {
   initCamera(holder);
  } else {
   holder.addCallback(this);
   holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  }
  mDecodeFormats = null;
  mCharacterSet = null;
 }
 @Override
 protected void onPause() {
  super.onPause();
  if (mHandler != null) {
   mHandler.quitSynchronously();
   mHandler = null;
  }
  CameraManager.get().closeDriver();
 }
 @Override
 protected void onDestroy() {
  mInactivityTimer.shutdown();
  mBeepManager.releaseRing();
  super.onDestroy();
 }
 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 }
 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  if (!hasSurface) {
   hasSurface = true;
   initCamera(holder);
  }
 }
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  hasSurface = false;
 }
 private void initCamera(SurfaceHolder holder) {
  try {
   CameraManager.get().openDriver(holder);
  } catch (Exception e) {
   e.printStackTrace();
  }
  if (mHandler == null) {
   mHandler = new CaptureActivityHandler(this, mDecodeFormats, mCharacterSet);
  }
 }
 //继承CaptureActivity的Activity类,如果SurfaceView的id和CaptureActivity布局中SurfaceView的id不同
 //需要重写这个方法,返回自己布局中的SurfaceView
 public SurfaceView getSurfaceView() {
  return mSurfaceView;
 }
 //继承CaptureActivity的Activity类,如果ViewfinderView的id和CaptureActivity布局中ViewfinderView的id不同
 //需要重写这个方法,返回自己布局中的ViewfinderView
 public ViewfinderView getViewfinderView() {
  return mViewfinderView;
 }
 public Handler getHandler() {
  return mHandler;
 }
 public void drawViewfinder() {
  getViewfinderView().drawViewfinder();
 }
 //处理扫描后的结果
 public void handleDecode(Result result, Bitmap bitmap) {
  mInactivityTimer.onActivity();
  if (result != null) {
   String text = result.getText();
   Log.i(TAG, "识别的结果:" + text);
   if (!TextUtils.isEmpty(text)) { //识别成功
    playBeepSoundAndVibrate();
    returnQRCodeResult(text);
   } else {
    showToast("很抱歉,识别二维码失败!");
   }
  } else {
   showToast("未发现二维码!");
  }
 }
 private void playBeepSoundAndVibrate() {
  if (isPlayBeep) {
   mBeepManager.startRing(); //播放扫码的滴滴声
  }
  if (isVibrate) {
   Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
   if (vibrator != null) {
    vibrator.vibrate(200); //震动200毫秒
   }
  }
 }
 //返回扫描结果
 private void returnQRCodeResult(String result) {
  Intent intent = new Intent();
  intent.putExtra(QRConstant.SCAN_QRCODE_RESULT, result);
  setResult(Activity.RESULT_OK, intent);
  finish();
 }
 private void showToast(CharSequence text) {
  runOnUiThread(() -> {
   ToastUtil.INSTANCE.showToast(text, true, false, getApplicationContext());
  });
 }
 @Override
 protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (requestCode == IMAGE_PICKER && resultCode == Activity.RESULT_OK) {
   if (data != null) {
    Uri uri = data.getData();
    if (uri != null) {
     Cursor cursor = getContentResolver().query(uri, null, null, null, null);
     if (cursor != null) {
      if (cursor.moveToFirst()) {
       mPhotoPath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
      }
      cursor.close();
      if (!TextUtils.isEmpty(mPhotoPath)) {
       //可以加个提示正在扫描的加载框,如showLoadingDialog("正在扫描...")
       new Thread(() -> {
        handleDecode(QRCodeUtil.decodeImage(mPhotoPath), null);
        //取消加载框,dismissLoadingDialog()
       }).start();
      } else {
       Log.e(TAG, "未找到图片");
      }
     }
    }
   }
  }
 }
}

 看一下使用的例子

      

最后,附上整个项目的github地址,注:项目使用了视图绑定ViewBinding,所以需要使用AndroidStudio 3.6.x版本。

加载全部内容

相关教程
猜你喜欢
用户评论