Ошибка: «Камера: не удалось активировать уже отключенный вариант использования» - PullRequest
0 голосов
/ 20 апреля 2020

Попытка использовать CameraX со сканером штрих-кода Firebase для сканирования штрих-кода.

Получение следующей ошибки:

Камера: не удалось установить уже отключенный вариант использования активным

Версии библиотеки:

// Камера X
cameraXVersion = "1.0.0-beta02"

// Версия для камеры
cameraViewVersion = "1.0.0-alpha08"

// Firebase ML vision
firebaseMlVisionVersion = "24.0.1"

// Модель штрих-кода Firebase ML
firebaseMlVisionBarcodeModelVersion = "16.0. 2 "

Сканер штрих-кода:

class BarcodeScanner(
    private val previewView: PreviewView,
    private val cameraExecutor: ExecutorService,
    private val context: Context,
    private val lifecycleOwner: LifecycleOwner,
    private val qrCodeAnalyser: QrCodeAnalyser
) {

    private var screenAspectRatio: Int
    private var rotation: Int
    private lateinit var cameraProvider: ProcessCameraProvider
    private var cameraSelector: CameraSelector
    private lateinit var preview: Preview
    private lateinit var imageAnalysis: ImageAnalysis
    private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>

    init {

        screenAspectRatio = getAspectRatio(previewView)
        if (LOGGING_ENABLED) {
            Log.e(TAG, "Preview aspect ratio: $screenAspectRatio")
        }

        rotation = previewView.display.rotation

        // Bind the camera provider to the life cycle owner
        cameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build()
    }


    // Declare and bind preview and analysis use cases
    fun bindCameraUseCases() {

        cameraProviderFuture = ProcessCameraProvider.getInstance(context)
        cameraProviderFuture.addListener(Runnable {

            // Camera provider
            cameraProvider = cameraProviderFuture.get()

            // Preview
            preview = Preview.Builder()
                // We request aspect ratio but no resolution
                .setTargetAspectRatio(screenAspectRatio)
                // Set initial target rotation
                .setTargetRotation(rotation)
                .build()

            // Attach the viewfinder's surface provider to preview use case
            preview.setSurfaceProvider(previewView.previewSurfaceProvider)

            // Image analysis
            imageAnalysis = ImageAnalysis.Builder()
                // We request aspect ratio but no resolution
                .setTargetAspectRatio(screenAspectRatio)
                // Set initial target rotation, we will have to call this again if rotation changes
                // during the lifecycle of this use case
                .setTargetRotation(rotation)
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                .build()
                // The analyzer can then be assigned to the instance
                .also { it.setAnalyzer(cameraExecutor, qrCodeAnalyser) }

            // Must unbind the use-cases before rebinding them
            unbindCameraUseCases()

            try {
                // A variable number of use-cases can be passed here -
                // camera provides access to CameraControl & CameraInfo
                cameraProvider.bindToLifecycle(
                    lifecycleOwner, cameraSelector, preview, imageAnalysis
                )
            } catch (exc: Exception) {

                if (LOGGING_ENABLED) {
                    Log.e(TAG, "Use case binding failed", exc)
                }
            }
        }, ContextCompat.getMainExecutor(context))
    }

    fun unbindCameraUseCases() {

        cameraProvider.unbindAll()
    }

    //  Detecting the most suitable ratio for dimensions provided in @params by counting absolute
    //  of preview ratio to one of the provided values.
    private fun getAspectRatio(previewView: PreviewView): Int {

        // Get screen metrics used to setup camera for full screen resolution
        val metrics = DisplayMetrics().also { previewView.display.getRealMetrics(it) }
        if (LOGGING_ENABLED) {
            Log.e(TAG, "Screen metrics: ${metrics.widthPixels} x ${metrics.heightPixels}")
        }

        val width = metrics.widthPixels
        val height = metrics.heightPixels

        val previewRatio = max(width, height).toDouble() / min(width, height)
        if (abs(previewRatio - RATIO_4_3_VALUE) <= abs(previewRatio - RATIO_16_9_VALUE)) {
            return AspectRatio.RATIO_4_3
        }
        return AspectRatio.RATIO_16_9
    }


    companion object {

        private const val RATIO_4_3_VALUE = 4.0 / 3.0
        private const val RATIO_16_9_VALUE = 16.0 / 9.0
        private const val TAG = "Barcode Scanner"
        private val LOGGING_ENABLED = BuildConfig.DEBUG && loggingEnabled && barcodeLoggingEnabled
    }
}

Макет XML:

<androidx.camera.view.PreviewView
    android:id="@+id/view_finder"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

Завернуто в макет ограничения .

Код фрагмента:

private lateinit var barcodeScanner: BarcodeScanner
private val cameraExecutor = Executors.newSingleThreadExecutor()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    startBarcodeScanner()
}


private fun startBarcodeScanner() {

    val qrCodeAnalyser = QrCodeAnalyser { qrCodes ->

        qrCodes.forEach { qrCode ->

            qrCode.rawValue?.let { qrCodeValue ->

                Log.e(TAG, "QR Code detected: ${qrCode.rawValue}.")
                // Use case is to detect only the first QR code and then process it and navigate to next fragment

                if (::barcodeScanner.isInitialized) {
                    barcodeScanner.unbindCameraUseCases()
                }
                // Shut down our background executor
                cameraExecutor.shutdown()
            }
        }
    }

    barcodeScanner = BarcodeScanner(
        view_finder,
        cameraExecutor,
        requireContext(),
        viewLifecycleOwner,
        qrCodeAnalyser
    )

    view_finder.post {
        barcodeScanner.bindCameraUseCases()
    }
}

override fun onPause() { 
    super.onPause()
    if (::barcodeScanner.isInitialized) {
        barcodeScanner.unbindCameraUseCases()
    }
}

override fun onResume() {
    super.onResume()
    view_finder.post {
        if (::barcodeScanner.isInitialized) {
            barcodeScanner.bindCameraUseCases()
        }
    }
}

override fun onDestroyView() {
    super.onDestroyView()

    if (::barcodeScanner.isInitialized) {
        barcodeScanner.unbindCameraUseCases()
    }
    // Shut down our background executor
    cameraExecutor.shutdown()
}

Весь несущественный код удаляется.

Сценарий, когда я получаю ошибку сообщение:

При переходе к фрагменту во 2-й и последующие периоды. Нет сообщения об ошибке в первый раз.

Любая помощь приветствуется.

Добавление полной трассировки стека:

D/Camera: Use cases [Preview:androidx.camera.core.Preview-2b628f3b-651e-4185-8816-bacd182d7739, ImageAnalysis:androidx.camera.core.ImageAnalysis-16478fc0-c1ff-4cac-9fa0-46e218202cee] now ONLINE for camera 0 
D/UseCaseAttachState: Active and online use case: [] for camera: 0
D/Camera: Resetting Capture Session  
D/Camera: releasing session in state INITIALIZED  
D/Camera: Transitioning camera internal state: INITIALIZED --    OPENING  
D/Camera: Opening camera: 0  
D/UseCaseAttachState: All use case: [androidx.camera.core.ImageAnalysis-16478fc0-c1ff-4cac-9fa0-46e218202cee, androidx.camera.core.Preview-2b628f3b-651e-4185-8816-bacd182d7739] for camera: 0  
I/CameraManager: Using legacy camera HAL.  
I/art: Background partial concurrent mark sweep GC freed 26391(1116KB) AllocSpace objects, 27(17MB) LOS objects, 40% free, 20MB/33MB, paused 7.112ms total 172.514ms  
D/Camera: Use case ImageAnalysis:androidx.camera.core.ImageAnalysis-16478fc0-c1ff-4cac-9fa0-46e218202cee ACTIVE for camera 0  
E/Camera: Failed to set already detached use case active  
D/Camera: Use case Preview:androidx.camera.core.Preview-2b628f3b-651e-4185-8816-bacd182d7739 ACTIVE for camera 0  
E/Camera: Failed to set already detached use case active  
D/Camera: Use cases [ImageAnalysis:androidx.camera.core.ImageAnalysis-16478fc0-c1ff-4cac-9fa0-46e218202cee] now OFFLINE for camera 0  
D/UseCaseAttachState: Active and online use case: [] for camera: 0  
D/Camera: Resetting Capture Session  
D/Camera: releasing session in state OPENING  
D/Camera: Use case Preview:androidx.camera.core.Preview-2b628f3b-651e-4185-8816-bacd182d7739 INACTIVE for camera 0  
D/UseCaseAttachState: Active and online use case: [] for camera: 0  
D/Camera: Use cases [Preview:androidx.camera.core.Preview-2b628f3b-651e-4185-8816-bacd182d7739] now OFFLINE for camera 0  
D/Camera: Resetting Capture Session  
D/Camera: releasing session in state OPENING  
D/Camera: Closing camera: 0  
D/Camera: Transitioning camera internal state: OPENING --    CLOSING  
D/UseCaseAttachState: Active and online use case: [] for camera: 0  
D/UseCaseAttachState: Active and online use case: [] for camera: 0  
D/Camera: Use cases [ImageAnalysis:androidx.camera.core.ImageAnalysis-e1f008e1-b782-4a19-940a-e75166d230a5, Preview:androidx.camera.core.Preview-4021921f-00eb-46dd-bce5-fb77d209bd34] now ONLINE for camera 0  
D/UseCaseAttachState: Active and online use case: [] for camera: 0  
D/Camera: Resetting Capture Session  
D/Camera: releasing session in state CLOSING  
D/Camera: Transitioning camera internal state: CLOSING --    REOPENING  
D/Camera: Use case ImageAnalysis:androidx.camera.core.ImageAnalysis-e1f008e1-b782-4a19-940a-e75166d230a5 ACTIVE for camera 0  
D/UseCaseAttachState: Active and online use case: [androidx.camera.core.ImageAnalysis-e1f008e1-b782-4a19-940a-e75166d230a5] for camera: 0  
D/Camera: Use case Preview:androidx.camera.core.Preview-4021921f-00eb-46dd-bce5-fb77d209bd34 ACTIVE for camera 0  
D/UseCaseAttachState: Active and online use case: [androidx.camera.core.Preview-4021921f-00eb-46dd-bce5-fb77d209bd34, androidx.camera.core.ImageAnalysis-e1f008e1-b782-4a19-940a-e75166d230a5] for camera: 0  
D/Camera: CameraDevice.onOpened(): 0  
D/Camera: Transitioning camera internal state: REOPENING --    OPENED  
D/UseCaseAttachState: All use case: [androidx.camera.core.Preview-4021921f-00eb-46dd-bce5-fb77d209bd34, androidx.camera.core.ImageAnalysis-e1f008e1-b782-4a19-940a-e75166d230a5] for camera: 0  
D/CaptureSession: Opening capture session.  
I/CameraDeviceState: Legacy camera service transitioning to state CONFIGURING  
I/RequestThread-0: Configure outputs: 2 surfaces configured.  
D/Camera: app passed NULL surface  
I/CameraDeviceState: Legacy camera service transitioning to state IDLE  
D/CaptureSession: Attempting to send capture request onConfigured  
D/CaptureSession: Issuing request for session.  
I/RequestQueue: Repeating capture request set.  
D/CaptureSession: CameraCaptureSession.onConfigured() mState=OPENED  
D/CaptureSession: CameraCaptureSession.onReady() OPENED  
W/LegacyRequestMapper: convertRequestMetadata - control.awbRegions setting is not supported, ignoring value  
W/LegacyRequestMapper: Only received metering rectangles with weight 0.  
W/LegacyRequestMapper: Only received metering rectangles with weight 0.  
I/art: Background partial concurrent mark sweep GC freed 12590(707KB) AllocSpace objects, 1(608KB) LOS objects, 40% free, 20MB/34MB, paused 2.229ms total 165.276ms  
I/CameraDeviceState: Legacy camera service transitioning to state CAPTURING  

1 Ответ

0 голосов
/ 21 апреля 2020

Я создал проблему в системе отслеживания проблем Google:
https://issuetracker.google.com/issues/154422490?enable_mat=true

И ответ:

Спасибо за регистрацию этой проблемы, эту проблему можно смело игнорировать - у нас есть задача по ненужному удалению регистрации. Это должно быть исправлено в ближайшее время.

...