Android集成zxing扫码框架功能

我们知道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版本。

到此这篇关于Android集成zxing扫码框架功能的文章就介绍到这了,更多相关android zxing扫码内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android上使用ZXing识别条形码与二维码的方法

    目前有越来越多的手机具备自动对焦的拍摄功能,这也意味着这些手机可以具备条码扫描的功能.手机具备条码扫描的功能,可以优化购物流程,快速存储电子名片(二维码)等. 本文所述实例就使用了ZXing 1.6实现条码/二维码识别.ZXing是个很经典的条码/二维码识别的开源类库,早在很久以前,就有开发者在J2ME上使用ZXing了,只不过需要支持JSR-234规范(自动对焦)的手机才能发挥其威力,而目前已经有不少Android手机具备自动对焦的功能. 本文代码运行的结果如下,使用91手机助手截图时,无法截

  • Android二维码的生成与扫码-zxing示例代码

    由于GitHub上面的zxing功能太多,有的用不到,我就抽取了重要的出来使用,这个可以生成二维码,扫描二维码和相册中的二维码 Demo效果: 1.在project的build.gradle添加如下代码: allprojects { repositories { maven { url 'https://jitpack.io' } } } 2.在build.gradle添加依赖: dependencies { compile 'com.github.goodboy321:Scan-Zxing:1

  • Android sdutio配置Zxing进行扫码功能的实现方法

    github开源项目(Zxing)demo 最快的调用Zxing方法 1.关联第三方库 2.调用基础的扫码 3.获取返回值 具体代码如下: //1.默认选项启动意图 new IntentIntegrator(MainActivity.this).initiateScan(); // `this` is the current Activity //2.获取得到的结果: @Override protected void onActivityResult(int requestCode, int r

  • Android中使用ZXing生成二维码(支持添加Logo图案)

    ZXing是谷歌的一个开源库,可以用来生成二维码.扫描二维码.本文所介绍的是第一部分. 首先上效果图: ZXing相关各种文件官方下载地址:https://github.com/zxing/zxing/releases 或者在这里下载(只有本项目所用的jar包,版本号:3.2.0):链接:http://pan.baidu.com/s/1pLqAR5x 1.生成二维码的工具类 /** * 二维码生成工具类 */ public class QRCodeUtil { /** * 生成二维码Bitmap

  • Android利用ZXing扫描二维码的实例代码解析

    相关阅读: Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题 此项目源码地址:请点击这里 看一下zxing的项目结构,我这里直接拿过来用的 看一下扫码的activity: package com.fanyafeng.barcode.activity; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle

  • 详解Android 扫描条形码(Zxing插件)

    使用Android Studio 一.在build.gradle(Module:app)添加代码  下载,调用插件 apply plugin: 'com.android.application' android { compileSdkVersion 24 buildToolsVersion "24.0.1" defaultConfig { applicationId "com.example.ly.scanrfid" minSdkVersion 19 target

  • Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

    先给大家展示下效果图: 扫描内容是下面这张,二维码是用zxing库生成的 由于改了好几个类,还是去年的事都忘得差不多了,所以只能上这个类的代码了,主要就是改了这个CaptureActivity.java package com.zxing.activity; import java.io.IOException; import java.util.Vector; import android.app.Activity; import android.content.Intent; import

  • Android集成zxing扫码框架功能

    我们知道zxing是一个强大的处理二维码和条形码等的开源库,本篇文章记录一下自己在项目中集成zxing开源库的过程. 导入依赖 implementation 'com.google.zxing:core:3.3.3' 申请权限 在AndroidManifest中申请相应权限: <!--相机--> <uses-permission android:name="android.permission.CAMERA" /> <!--震动--> <use

  • Android实现基于ZXing快速集成二维码扫描功能

    二维码扫描现在是一直比较多的应用场景,android的开源项目ZXing提供了完整.成熟的解决方案,如果仅仅是出于快速开发的目的,可以根据自己的项目需要,把ZXing官方提供的项目稍加裁剪,就可以快速的集成到自己的项目中.下面详细演示和介绍如何实现基于ZXing官方提供的源码,快速集成二维码扫描功能到自己项目中的解决方案. (第1步):到ZXing官方主页下载最新的项目代码包,ZXing在github的官方主页:https://github.com/zxing,下载后解压.解压后根目录下有若干项

  • Android 连接蓝牙扫码器无输入框的实现

    Android 的APP 需要集成一个蓝牙扫码器, 特别的是,需要扫码的地方是没有输入框的(EditText),不能通过直觉上理解的通过对EditText输入事件进行监听处理,取得扫码结果.并且设备也没有提供SDK. 细想了一下, 蓝牙扫码器本质应该是个HID设备,相当于蓝牙键盘.而后豁然开朗. 每一次扫码应该会触发按键事件,通过监听当前Activity的按键事件,应该可以实现,无输入框的情况下取得扫码结果. 重载Activity中的dispatchKeyEvent实现按键监听. @Overri

  • 基于 Swoole 的微信扫码登录功能实现代码

    随着微信的普及,扫码登录方式越来越被现在的应用所使用.它因为不用去记住密码,只要有微信号即可方便快捷登录.微信的开放平台原生就有支持扫码登录的功能,不过大部分人还是在用公众平台,所以扫码登录只能自行实现.这里基于微信公众平台的带参数临时二维码,并且结合 Swoole 的 WebSocket 服务实现扫码登录.大体流程如下: 客户端打开登录界面,连接到 WebSocket 服务 WebScoket 服务生成带参数二维码返回给客户端 用户扫描展示的带参数二维码 微信服务器回调扫码事件并通知开发者服务

  • 详解java实现简单扫码登录功能(模仿微信网页版扫码)

    java实现简单扫码登录功能 模仿微信pc网页版扫码登录 使用js代码生成qrcode二维码减轻服务器压力 js循环请求服务端,判断是否qrcode被扫 二维码超时失效功能 二维码被扫成功登录,服务端产生sessionId,传到页面使用js保存cookie 多线程 生成qrcode相关js jquery.qrcode.js 代码 页面div <div class="pc_qr_code"> <input type="hidden" id="

  • 基于C#实现微信支付宝扫码支付功能

    为公司系统业务需要,这几天了解了一下微信和支付宝扫码支付的接口,并用c#实现了微信和支付宝扫码支付的功能. 微信支付分为6种支付模式:1.付款码支付,2.native支付,3.jsapi支付,4.app支付,5.h5支付,6.小程序支付 我在这里用到的是native支付,就是网页生成二维码让用户扫码支付,再调用回调接口判断用户是否支付成功. 支付宝支付api也挺多的,我只使用了一些我在系统中能够用到的,现在将代码简单记录在这里,先从微信支付开始. 微信支付 先上后台代码: 传入参数(总金额一定要

  • Spring Boot实现微信扫码登录功能流程分析

    目录 1. 授权流程说明 第一步:请求CODE 第二步:通过code获取access_token 第三步:通过access_token调用接口 2. 授权流程代码 3. 用户登录和登出 4. Spring AOP校验用户有没有登录 5. 拦截登录校验不通过抛出的异常 微信开放平台:微信扫码登录功能 官方文档:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html 1. 授权

  • Vue PC端实现扫码登录功能示例代码

    目录 需求描述 思路解析 前端功能实现 如何控制二维码的时效性? 前端如何获取服务器二维码的状态? 本篇文章给大家带来了关于Vue的相关知识,其中主要介绍了在PC端实现扫码的原理是什么?怎么生成二维码图片?怎么用Vue实现前端扫码登录?感兴趣的朋友,下面一起来看一下吧,希望对大家有帮助. 需求描述 目前大多数PC端应用都有配套的移动端APP,如微信,淘宝等,通过使用手机APP上的扫一扫功能去扫页面二维码图片进行登录,使得用户登录操作更方便,安全,快捷. 思路解析 PC 扫码原理? 扫码登录功能涉

  • java实现在SSM下使用支付宝扫码支付功能

    本文实例为大家分享了java使用支付宝扫码支付的具体代码,供大家参考,具体内容如下 准备工作 首先开通支付宝沙箱的测试账号,里面会有消费者账户和收款方账户 手机扫码下载手机端app 基础配置 所需jar包 AlipayConfig package com.alipay.config; import java.io.FileWriter; import java.io.IOException; import java.util.ResourceBundle; /* * *类名:AlipayConf

  • jQuery实现“扫码阅读”功能

    今天看到一个用户发了个话题,"PC端的URL在移动端上打开要一个个敲好麻烦,有什么好的办法?". 确实现在已经是移动时代了,在移动设备上阅读慢慢会成为主流,网站如果没有便捷的方式让用户在移动设备阅读的话还真有点落伍,于是想想就做个"扫码阅读"的功能吧.其实很简单,就是将网址生成二维码就行了. 无论用PHP生成,还是用JavaScript生成都是可以的,从代码改动来说,用JavaScript会更省事些.所以这里就用jQuery吧.正好网上有个 jquery.qrcod

随机推荐