android camera X已被另一个startFocusAndMetering取消

txu3uszq  于 2023-06-04  发布在  Android
关注(0)|答案(3)|浏览(309)

我正在使用cameraX库实现一个自定义相机。我正在努力集中注意力,我做了下面的事情

viewFinder.setOnTouchListener { v, event ->
            return@setOnTouchListener when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    true
                }
                MotionEvent.ACTION_UP -> {
                   // The below code is for focusing 

                    val factory = SurfaceOrientedMeteringPointFactory(
                        viewFinder.width.toFloat(),
                        viewFinder.height.toFloat()
                    )
                    val point = factory.createPoint(event.x, event.y)
                    try {
                        val action = FocusMeteringAction.Builder(point, FocusMeteringAction.FLAG_AF)
                            .apply {
                                disableAutoCancel() //focus only when the user tap the preview
                            }.build()

                        val future = cameraControl?.startFocusAndMetering(action)
                        future?.addListener(Runnable {
--->line 66                 val result = future?.get()
                            println("log result ---> $result")
                        }, cameraExecutor)

                    } catch (e: CameraInfoUnavailableException) {
                        println("log error ---> $e")
                    }
                    true
                }
                else -> false // Unhandled event.
            }
        }

现在,它是一些什么聚焦点,我触摸,它不是太准确,但它的确定.而在5到6次聚焦后,应用程序崩溃并关闭。

FATAL EXCEPTION: pool-2-thread-1
...
...
java.lang.Error: java.util.concurrent.ExecutionException: androidx.camera.core.CameraControl$OperationCanceledException: Cancelled by another startFocusAndMetering()
...
...
...MainActivity$onCreate$2$1.run(MainActivity.kt:66)

我不明白为什么它会崩溃,而且它并不经常崩溃。有时它会崩溃,有时不会。
编辑1:-
我知道当我多次点击焦点时,就会发生这种情况。因此,在开始对焦之前,我需要清除之前的对焦(如果正在进行)。但是,如何清除以前的重点,我不明白。
编辑2:-
我尝试了这个cameraControl?.cancelFocusAndMetering(),我只是把它放在try块的第一行。但问题仍然存在。

83qze16e

83qze16e1#

在此为Java代码道歉。但根据我的经验未来呢?.get()需要 Package 在try,catch中

future.addListener(() -> {

    try
        {
            FocusMeteringResult result = (FocusMeteringResult) future.get();
            if(result.isFocusSuccessful())
            {
                // Focus has succeeded
            }
            else
            {
                // Focus has failed
            }
        }
        catch (ExecutionException e) // Thrown exceptions
        {
            e.printStackTrace();
        }
        catch (InterruptedException e) // Thrown exceptions
        {
            e.printStackTrace();
        }
}
xdnvmnnf

xdnvmnnf2#

我刚把这个块拿掉

future?.addListener(Runnable {
          val result = future?.get()
          println("log result ---> $result")
       }, cameraExecutor)

而且运行良好但我不知道这是对还是错。
如果有人知道?请回答。目前我把它标记为答案,因为它工作了。

g6baxovj

g6baxovj3#

正如你所说的问题是由于未来?. addListener。要解决这个问题,您可以在viewFinder.setOnTouchListener外部定义future变量:

private var future: ListenableFuture<FocusMeteringResult>? = null

在调用startFocusAndMetering(action)之前取消future

future?.cancel(true)

所以你的最终代码看起来像这样:

private var future: ListenableFuture<FocusMeteringResult>? = null

viewFinder.setOnTouchListener { v, event ->
            return@setOnTouchListener when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    true
                }
                MotionEvent.ACTION_UP -> {
                   
                    future?.cancel(true)

                    // The below code is for focusing 

                    val factory = SurfaceOrientedMeteringPointFactory(
                        viewFinder.width.toFloat(),
                        viewFinder.height.toFloat()
                    )
                    val point = factory.createPoint(event.x, event.y)
                    try {
                        val action = FocusMeteringAction.Builder(point, FocusMeteringAction.FLAG_AF)
                            .apply {
                                disableAutoCancel() //focus only when the user tap the preview
                            }.build()

                        future = cameraControl?.startFocusAndMetering(action)
                        future?.addListener(Runnable {
--->line 66                 val result = future?.get()
                            println("log result ---> $result")
                        }, cameraExecutor)

                    } catch (e: CameraInfoUnavailableException) {
                        println("log error ---> $e")
                    }
                    true
                }
                else -> false // Unhandled event.
            }
        }

相关问题