在单独的线程中关闭相机设备
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线程上进行这些操作也是一个好主意。
就是说,只要您没有忘记自己的应用状态(例如,这样您就不会尝试使用您已经意外关闭的相机设备),就没有理由您不能混合调用相机设备或从多个线程捕获会话。 类 本身是线程安全的。
我正在使用 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线程上进行这些操作也是一个好主意。
就是说,只要您没有忘记自己的应用状态(例如,这样您就不会尝试使用您已经意外关闭的相机设备),就没有理由您不能混合调用相机设备或从多个线程捕获会话。 类 本身是线程安全的。