在单独的线程中关闭相机设备

Close CameraDevice in a seperate thread

我正在使用 Android camera2 创建自定义相机。 cameraDevice.close() 方法很慢,它会使 UI 冻结 1 秒。我把它放在另一个线程中,它似乎工作得很好。我想知道这是否会导致一些严重的问题,以及是否有另一种方法可以实现这一目标。这是我的 closeCamera 方法:

private void closeCamera() {
    boolean release = false;
    try {
        mCameraOpenCloseLock.acquire();
        release = true;
    } catch (InterruptedException e) {
        release = false;
    }
    try {
        preparing = true;
        if (mCaptureSession != null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && mCaptureSession.isReprocessable()
                    || validCameraSession) {
                mCaptureSession.close();
            }
            mCaptureSession = null;
            validCameraSession = false;
        }
    } catch (IllegalStateException e) {
        mCaptureSession = null;
    } catch (Exception e) {
        mCaptureSession = null;
    }
    try {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (mCameraDevice != null) {
                    if (openCamera) {
                        mCameraDevice.close();
                        mCameraDevice = null;
                    }
                }
            }
        }).start();

    } catch (IllegalStateException e) {
        Log.e(TAG, "closeCamera: mCaptureSession - ", e);
    } catch (Exception e) {
        Log.e(TAG, "closeCamera: mCaptureSession - ", e);
    }

    if (release) {
        if (mCameraOpenCloseLock != null) {
            int lock = mCameraOpenCloseLock.availablePermits();
            if (lock > 1) mCameraOpenCloseLock.release(lock - 1);
            else if (lock == 0) mCameraOpenCloseLock.release();
        }
    }
}

我觉得mCameraDevice还没有关闭,用户又打开相机可能会导致崩溃。但这种情况很少见,我正在考虑在再次打开相机之前再进行一次检查。我不希望我的 UI 冻结 1 秒以使其关闭,除了将它放在单独的线程中之外,还有其他方法可以实现吗?

据我所知,这种 cameraDevice.close() 的冻结发生在一些不幸的设备上,有时可以通过执行正常的系统升级来解决。

但是,如果您在您的设备上遇到这种情况,这有点安慰。实际上,您很幸运可以为此准备一个修复程序。您应用的最终用户将从您的不幸中受益。

您的代码看起来不错,如果它为您提供了所需的改进。正如我所解释的,可能很难在另一台设备上重现此问题。

我宁愿将所有 closeCamera() 逻辑放在同一个后台线程上。如果您向 openCamera() 提供了 Handler,如 in the official example,

manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);

然后我会建议 posting 所有 closeCamera() 序列到这个 mBackgroundHandler.

正如 Alex Cohn 所提到的,推荐的做法是在与 UI 不同的线程上完成所有与相机相关的工作。

相对来说,打开相机或创建捕获会话也需要很长时间,所以不在UI线程上进行这些操作也是一个好主意。

就是说,只要您没有忘记自己的应用状态(例如,这样您就不会尝试使用您已经意外关闭的相机设备),就没有理由您不能混合调用相机设备或从多个线程捕获会话。 类 本身是线程安全的。