使用CameraX与Android ML Kit实现扫码时出现cancelBuffer: BufferQueue has been abandoned警告的问题求助
CameraX与Android ML Kit实现扫码时出现cancelBuffer: BufferQueue has been abandoned警告的问题求助
我在用CameraX搭配ML Kit做二维码扫描功能的时候,每次退出扫描相机界面,或者扫完一个二维码之后,都会在Logcat里看到这条警告:
SurfaceView - com.example.myapp/com.example.myapp.MainActivity@a9c00b0@0#0 cancelBuffer: BufferQueue has been abandoned
虽然扫码的核心功能是正常工作的,但这个警告一直存在,我想搞清楚它的成因,以及有没有办法能消除这个警告?
以下是我的代码实现:
抽象扫描Fragment类
abstract class QrScannerGenericFragment : Fragment() { // UI private lateinit var previewView: PreviewView private lateinit var scannerProgressBar: ProgressBar private lateinit var scannerTextView: TextView private lateinit var cameraProvider: ProcessCameraProvider private lateinit var analysisUseCase: ImageAnalysis private var rgbaBitmap: Bitmap? = null private val cameraExecutor by lazy { Executors.newSingleThreadExecutor() } private val scanner by lazy { val options = BarcodeScannerOptions.Builder() .setBarcodeFormats(Barcode.FORMAT_QR_CODE) .build() BarcodeScanning.getClient(options) } // HELPERS private var scanned = false private var infoListener: InfoListener? = null // BINDING private var _binding: FragmentQrScannerBinding? = null private val binding get() = _binding!! override fun onAttach(context: Context) { super.onAttach(context) if (context is InfoListener) { infoListener = context } else { throw RuntimeException("$context must implement InfoListener") } } override fun onCreateView( inflater: LayoutInflater, parent: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = FragmentQrScannerBinding.inflate(inflater, parent, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) previewView = binding.scannerPreviewView scannerProgressBar = binding.scannerProgressBar scannerTextView = binding.scannerTextView previewView.previewStreamState.observe(viewLifecycleOwner) { state -> when (state) { PreviewView.StreamState.IDLE -> { scannerProgressBar.visibility = View.VISIBLE scannerTextView.visibility = View.GONE } PreviewView.StreamState.STREAMING -> { scannerProgressBar.visibility = View.GONE scannerTextView.visibility = View.VISIBLE } } } startCamera() } private fun startCamera() { scannerProgressBar.visibility = View.VISIBLE val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext()) cameraProviderFuture.addListener({ cameraProvider = cameraProviderFuture.get() val previewUseCase = Preview.Builder() .build() .also { it.setSurfaceProvider(previewView.surfaceProvider) } analysisUseCase = ImageAnalysis.Builder() .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .build() .also { useCase -> useCase.setAnalyzer(cameraExecutor) { imageProxy -> processImageProxy(imageProxy) } } val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA cameraProvider.unbindAll() cameraProvider.bindToLifecycle( viewLifecycleOwner, cameraSelector, previewUseCase, analysisUseCase ) }, ContextCompat.getMainExecutor(requireContext())) } private fun processImageProxy(imageProxy: ImageProxy) { try { val width = imageProxy.width val height = imageProxy.height if (rgbaBitmap == null || rgbaBitmap?.width != width || rgbaBitmap?.height != height ) { rgbaBitmap?.recycle() rgbaBitmap = createBitmap(width, height) } val buffer = imageProxy.planes[0].buffer buffer.rewind() rgbaBitmap!!.copyPixelsFromBuffer(buffer) val inputImage = InputImage.fromBitmap(rgbaBitmap!!, imageProxy.imageInfo.rotationDegrees) scanner.process(inputImage) .addOnSuccessListener { barcodes -> if (!scanned) { barcodes.firstOrNull()?.rawValue?.let { value -> scanned = true requireActivity().runOnUiThread { onQrcodeDetected(value) } } } } .addOnFailureListener { e -> Log.e(LOGCAT_TAG, "Błąd skanowania", e) } } catch (e: Exception) { Log.e(LOGCAT_TAG, "Error processing imageProxy", e) } finally { imageProxy.close() } } override fun onResume() { super.onResume() scanned = false } override fun onStop() { if (::cameraProvider.isInitialized) { cameraProvider.unbindAll() } super.onStop() } override fun onDestroyView() { super.onDestroyView() if (::cameraProvider.isInitialized) { cameraProvider.unbindAll() } cameraExecutor.shutdown() scanner.close() rgbaBitmap?.run { if (!isRecycled) recycle() } rgbaBitmap = null _binding = null } protected abstract fun onQrcodeDetected(value: String) companion object { private const val LOGCAT_TAG = "Debug" } }
具体实现的扫描Fragment
class TrailsQrScannerFragment: QrScannerGenericFragment() { private var trailsQrScannerListener: TrailsQrScannerListener? = null override fun onAttach(context: Context) { super.onAttach(context) if(context is TrailsQrScannerListener){ trailsQrScannerListener = context }else { throw IllegalStateException("$context must implement TrailsQrScannerListener") } } override fun onQrcodeDetected(scannedText: String) { trailsQrScannerListener?.onTrailQrcodeDetected(scannedText) } }
我在MainActivity中实现了对应的Listener接口,整体功能运行正常,就是这个警告一直挥之不去,希望能得到大家的帮助!
内容来源于stack exchange
相关产品推荐
相关产品推荐

