Skip to content

扫码

需要申请相机权限

com.journeyapps:zxing-android-embedded

https://github.com/journeyapps/zxing-android-embedded

依赖

xml
    implementation 'com.journeyapps:zxing-android-embedded:4.3.0'

硬件加速

xml
    <application android:hardwareAccelerated="true" ... >

xml

xml
<com.journeyapps.barcodescanner.BarcodeView
    android:id="@+id/barcodeView"
    android:layout_width="300dp"
    android:layout_height="300dp"/>

初始化

java
binding.barcodeView.setDecoderFactory(new DefaultDecoderFactory(List.of(BarcodeFormat.QR_CODE)));
binding.barcodeView.decodeSingle(result -> {
    currentText = result.getText();
});

绑定生命周期

java
    @Override
    protected void onResume() {
        super.onResume();
        binding.barcodeView.resume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        binding.barcodeView.pause();
    }`

自定义

https://blog.csdn.net/Ikulm/article/details/121529753

com.github.jenly1314:zxing-lite

https://github.com/jenly1314/ZXingLite

依赖

xml
implementation 'com.github.jenly1314:zxing-lite:3.3.0'

使用

java
import android.content.Context;
import android.content.Intent;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.zxing.Result;
import com.king.camera.scan.AnalyzeResult;
import com.king.camera.scan.CameraScan;
import com.king.camera.scan.analyze.Analyzer;
import com.king.zxing.BarcodeCameraScanActivity;
import com.king.zxing.DecodeConfig;
import com.king.zxing.DecodeFormatManager;
import com.king.zxing.analyze.MultiFormatAnalyzer;

import timber.log.Timber;

public class QRCodeScanActivity extends BarcodeCameraScanActivity {

    @Override
    public void initCameraScan(@NonNull CameraScan<Result> cameraScan) {
        super.initCameraScan(cameraScan);
        // 根据需要设置CameraScan相关配置
        cameraScan.setPlayBeep(true);
    }

    @Nullable
    @Override
    public Analyzer<Result> createAnalyzer() {
        // 初始化解码配置
        DecodeConfig decodeConfig = new DecodeConfig();
        decodeConfig.setHints(DecodeFormatManager.QR_CODE_HINTS)//如果只有识别二维码的需求,这样设置效率会更高,不设置默认为DecodeFormatManager.DEFAULT_HINTS
                .setFullAreaScan(false)//设置是否全区域识别,默认false
                .setAreaRectRatio(0.8f)//设置识别区域比例,默认0.8,设置的比例最终会在预览区域裁剪基于此比例的一个矩形进行扫码识别
                .setAreaRectVerticalOffset(0)//设置识别区域垂直方向偏移量,默认为0,为0表示居中,可以为负数
                .setAreaRectHorizontalOffset(0);//设置识别区域水平方向偏移量,默认为0,为0表示居中,可以为负数
        // BarcodeCameraScanActivity默认使用的MultiFormatAnalyzer,如果只识别二维码,这里可以改为使用QRCodeAnalyzer
        return new MultiFormatAnalyzer(decodeConfig);
    }

    /**
     * 布局ID;通过覆写此方法可以自定义布局
     *
     * @return 布局ID
     */
//    @Override
//    public int getLayoutId() {
//        return R.layout.activity_qrcode_scan;
//    }

    @Override
    public void onScanResultCallback(@NonNull AnalyzeResult<Result> result) {
        // 停止分析
        getCameraScan().setAnalyzeImage(false);
        // 返回结果
        Timber.d("onScanResultCallback: %s", result.getResult().getText());
//        finish();
    }

    public static void start(Context context) {
        Intent intent = new Intent(context, QRCodeScanActivity.class);
        context.startActivity(intent);
    }
}

com.google.mlkit:barcode-scanning

https://developers.google.com/ml-kit/vision/barcode-scanning/android

依赖

xml
    def camerax_version = "1.5.2"
    implementation "androidx.camera:camera-camera2:${camerax_version}"
    implementation "androidx.camera:camera-lifecycle:${camerax_version}"
    implementation "androidx.camera:camera-view:${camerax_version}"
    implementation 'com.google.mlkit:barcode-scanning:17.3.0'

xml

xml
<androidx.camera.view.PreviewView
    android:id="@+id/preview"
    android:layout_width="300dp"
    android:layout_height="300dp" />

初始化

java
// 创建条码扫描选项,仅扫描QR码格式
BarcodeScannerOptions options = new BarcodeScannerOptions.Builder()  
        .setBarcodeFormats(Barcode.FORMAT_QR_CODE)  
        .build();  

// 初始化条码扫描器
BarcodeScanner scanner = BarcodeScanning.getClient(options);  

// 创建图像分析器,设置为只保留最新的图像帧
imageAnalysis = new ImageAnalysis.Builder()  
        .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)  
        .build();  

// 设置图像分析器的分析器
imageAnalysis.setAnalyzer(getMainExecutor(), image -> {  
    // 获取图像数据
    Image mediaImage = image.getImage();  
    if (mediaImage != null) {  
        // 将图像转换为InputImage格式,包含旋转信息
        InputImage inputImage = InputImage.fromMediaImage(mediaImage, image.getImageInfo().getRotationDegrees());  
        
        // 执行条码扫描处理
        scanner.process(inputImage)  
                .addOnSuccessListener(barcodes -> {  
                    // 遍历扫描到的所有条码
                    for (Barcode barcode : barcodes) {  
                        String rawValue = barcode.getRawValue();  
                    }  
                })  
                .addOnFailureListener(Timber::e)  
                .addOnCompleteListener(task -> image.close()); // 处理完成后关闭图像
    }  
});  

// 获取相机提供者实例
cameraProviderFuture = ProcessCameraProvider.getInstance(this);  

// 相机提供者准备就绪后的回调
cameraProviderFuture.addListener(() -> {  
    try {  
        ProcessCameraProvider cameraProvider = cameraProviderFuture.get();  

        Preview preview = new Preview.Builder().build();  
        preview.setSurfaceProvider(binding.preview.getSurfaceProvider());  

        // 选择后置摄像头
        CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;  

        // 将预览、分析器绑定到生命周期
        Camera camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis);  
    } catch (Exception e) {  
        Timber.e(e); // 记录错误日志
    }  
}, getMainExecutor());

隐私问题

使用mlkit会向firebase发送log,注意隐私合规

https://firebase.google.com/docs/analytics/configure-data-collection?hl=zh-cn&platform=android

实测设置AndroidManifest.xml的值后仍在发送