You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

Android扫码异常:MlKitAnalyzer仅首次触发,重启Activity后失效

排查与解决方法

问题根源定位

首次启动正常、二次启动失效并出现SurfaceView - queueBuffer: BufferQueue has been abandoned错误,核心原因是相机资源未正确释放,导致第二次启动时无法正常获取Surface实例,进而使MlKitAnalyzer无法接收相机帧数据;同时代码中存在条码格式数组初始化的逻辑错误,可能加剧资源异常问题。


具体修复步骤

1. 修复Executor关闭逻辑

cameraExecutor.shutdown()是平缓关闭,可能残留未完成任务导致资源泄漏,改用shutdownNow()强制终止所有任务:

@Override
protected void onDestroy() {
    super.onDestroy();
    logger.info("destroy scanner activity");
    // 立即终止所有线程池任务,避免资源残留
    cameraExecutor.shutdownNow();
    if (cameraController != null) {
        cameraController.clearImageAnalysisAnalyzer();
    }
    if (barcodeScanner != null) {
        barcodeScanner.close();
    }
}

2. 移除手动解绑CameraController

LifecycleCameraController已绑定到Activity生命周期,会自动在Activity销毁时处理解绑逻辑,手动调用unbind()会导致生命周期状态不一致,引发Surface资源异常,直接删除cameraController.unbind()代码。

3. 修复条码格式数组初始化错误

原代码循环起始索引错误,导致finalFormats[0]为无效的0值,修改循环逻辑:

// 替换原finalFormats初始化代码
int[] finalFormats = formats.stream().mapToInt(Integer::intValue).toArray();

// 修复扫描器选项构建逻辑
BarcodeScannerOptions scannerOptions;
if (formats.isEmpty()) {
    scannerOptions = new BarcodeScannerOptions.Builder()
            .setBarcodeFormats(Barcode.FORMAT_QR_CODE)
            .build();
} else {
    // 拆分第一个格式与剩余格式,适配setBarcodeFormats的参数要求
    scannerOptions = new BarcodeScannerOptions.Builder()
            .setBarcodeFormats(formats.get(0), Arrays.copyOfRange(finalFormats, 1, finalFormats.length))
            .build();
}
barcodeScanner = BarcodeScanning.getClient(scannerOptions);

4. 调整finish()执行时机

在分析器回调中先停止分析器,再结束Activity,避免流程冲突:

cameraController.setImageAnalysisAnalyzer(cameraExecutor, new MlKitAnalyzer(List.of(barcodeScanner), COORDINATE_SYSTEM_VIEW_REFERENCED, cameraExecutor, (result) -> {

    logger.info("Got scanner result {}", result);
    if (result == null) return;
    List<Barcode> barcodeResults = result.getValue(barcodeScanner);
    if (barcodeResults == null ||
            barcodeResults.isEmpty() ||
            barcodeResults.get(0) == null) {
        return;
    }

    Barcode item = barcodeResults.get(0);
    Intent intent = new Intent();
    intent.putExtra("data", item.getRawValue());
    setResult(MyBarcodeScanner.REQUEST_CODE, intent);
    
    // 先清除分析器,再终止Activity
    cameraController.clearImageAnalysisAnalyzer();
    finish();
}));

5. 升级CameraX与ML Kit依赖

使用最新稳定版依赖,避免旧版本的生命周期管理bug:

implementation "androidx.camera:camera-core:1.3.0"
implementation "androidx.camera:camera-camera2:1.3.0"
implementation "androidx.camera:camera-lifecycle:1.3.0"
implementation "androidx.camera:camera-view:1.3.0"
implementation "com.google.mlkit:barcode-scanning:17.2.0"

内容的提问来源于stack exchange,提问作者Chi

火山引擎 最新活动