我正在阅读有关此问题的许多报道,但仍无法找到答案。 有时,在使用camera2捕获之后,会抛出异常:java.lang.IllegalStateException:会话已关闭;进一步的变化是非法的 我试图检查所有会话不是null,什么时候做某事,但仍然得到这个。 有什么建议吗?还有什么我应该处理?=,我没有?
private CameraCaptureSession.CaptureCallback mCaptureCallback
= new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult result) {
switch (mState) {
case STATE_PREVIEW: {
if(touchFocusEnabled) {
letSetCaptureSessionOnce = true;
mState = STATE_WAITING_LOCK;
try {
// Reset the auto-focus trigger
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
mHandler);
} catch (CameraAccessException e) {
L.e("CameraLolipop --- CameraCaptureSession.CaptureCallback " + e);
}
} else {
if(letSetCaptureSessionOnce) {
try {
if ((null != mCaptureSession) && (isCameraOpen)) {
mState = STATE_PREVIEW;
mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
mHandler);
letSetCaptureSessionOnce = true;
}
} catch (CameraAccessException e) {
L.e("CameraLolipop --- CameraCaptureSession.CaptureCallback " + e);
}
}
}
break;
}
case STATE_WAITING_LOCK: {
if(touchFocusEnabled) {
mState = STATE_PICTURE_TAKEN;
touchFocusEnabled = false;
try {
if((mCaptureSession != null) && (isCameraOpen)){
mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
mHandler);
}
} catch (CameraAccessException e) {
L.e("CameraLolipop --- STATE_WAITING_LOCK " + e);
}
return;
}
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
L.d("Focus state ", "STATE_WAITING_LOCK");
boolean fixedFocus = isFixedFocus();
if (afState == null) {
// if ((burstMode) && (getSupportedHardwareLevel() == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)) {
// captureStillPictureBurst();
// } else {
captureStillPicture();
// }
} else if ((CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) || fixedFocus) {
L.d("Focus state ", "CONTROL_AF_STATE_FOCUSED_LOCKED or CONTROL_AF_STATE_NOT_FOCUSED_LOCKED");
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
mState = STATE_PICTURE_TAKEN;
if ((burstMode) && (getSupportedHardwareLevel() == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)) {
// captureStillPictureBurst();
captureStillPicture();
} else {
captureStillPicture();
}
} else {
runPrecaptureSequence();
}
}
break;
}
case STATE_WAITING_PRECAPTURE: {
L.d("Focus state ", "STATE_WAITING_PRECAPTURE");
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED || isFixedFocus()) {
mState = STATE_WAITING_NON_PRECAPTURE;
}
break;
}
case STATE_WAITING_NON_PRECAPTURE: {
L.d("Focus state ", "STATE_WAITING_NON_PRECAPTURE");
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
mState = STATE_PICTURE_TAKEN;
if ((burstMode) && (getSupportedHardwareLevel() == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)) {
// captureStillPictureBurst();
captureStillPicture();
} else {
captureStillPicture();
}
}
break;
}
case STATE_PICTURE_TAKEN: {
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
L.d("TOUCH", " afState " + afState);
mState = STATE_PREVIEW;
if(afState == 4) {
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
}
if(afState == 0) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
mPreviewRequestBuilder
.set(CaptureRequest.CONTROL_AF_REGIONS, null);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
}
}, 2500);
}
break;
}
}
}
@Override
public void onCaptureProgressed(CameraCaptureSession session,
CaptureRequest request,
CaptureResult partialResult) {
super.onCaptureProgressed(session, request, partialResult);
// process(partialResult);
}
@Override
public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request,
TotalCaptureResult result) {
// if ((mState != STATE_PREVIEW) || (touchFocusEnabled)) {
super.onCaptureCompleted(session, request, result);
if(session != null) {
process(result);
}
}
};
这里是创建会话的地方:
private CameraCaptureSession.StateCallback mSessionPreviewStateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
L.i("Thread", "onConfigured---->" + Thread.currentThread().getName());
// The camera is already closed
if(null == mCameraDevice) {
return;
}
try {
mCaptureSession = cameraCaptureSession;
mCameraSessionIsClosed = false;
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
if((isCameraOpen) && (mCaptureSession != null)){
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mHandler);
}
L.d("ex0003", "Test... mSessionPreviewStateCallback ");
} catch (CameraAccessException e) {
L.e("CameraLolipop --- openCamera() " + e);
}
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
Toast.makeText(getActivity(), "onConfigureFailed---Preview", Toast.LENGTH_SHORT).show();
}
};
并在onPause中调用closeCamera():
try {
if(mCameraDevice == null && mCameraIsClosed) {
return;
}
if((mCaptureSession != null) && (isCameraOpen)) {
try {
mCaptureSession.abortCaptures();
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
mCameraOpenCloseLock.acquire();
if (null != mCaptureSession) {
mCaptureSession.close();
mCaptureSession = null;
mCameraSessionIsClosed = true;
}
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
isCameraOpen = false;
mCameraIsClosed = true;
}
if (null != mImageReader) {
mImageReader.close();
mImageReader = null;
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
} finally {
mCameraOpenCloseLock.release();
}
并在调用stopBackgroundThread()和super.onPause()之后。
答案 0 :(得分:0)
我不确定这是否有效,但请尝试一下,让我知道它是否有效。
private CameraCaptureSession.StateCallback mSessionPreviewStateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
L.i("Thread", "onConfigured---->" + Thread.currentThread().getName());
// The camera is already closed
if(null == mCameraDevice) {
return;
}
try {
mCaptureSession = cameraCaptureSession;
mCameraSessionIsClosed = false;
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
if((isCameraOpen) && (mCaptureSession != null)){
mPreviewRequest = mPreviewRequestBuilder.build();
mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mHandler);
}
L.d("ex0003", "Test... mSessionPreviewStateCallback ");
} catch (CameraAccessException e) {
Log.e(TAG, "Failed to start camera preview because it couldn't access camera", e);
} catch (IllegalStateException e) {
Log.e(TAG, "Failed to start camera preview.", e);
}
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
Toast.makeText(getActivity(), "onConfigureFailed---Preview", Toast.LENGTH_SHORT).show();
}
@Override
public void onClosed(@NonNull CameraCaptureSession session) {
if (mCaptureSession != null && mCaptureSession.equals(session)) {
mCaptureSession = null;
}
}
};
答案 1 :(得分:0)
如果在将所有配置设置为预览请求构建器之前打开相机,则会发生此错误。因此,您必须首先设置所有参数,如TextureView大小,相机输出大小等。 以下是来自Google的示例应用的代码:
setUpCameraOutputs(width, height);
configureTransform(width, height);
Activity activity = getActivity();
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
答案 2 :(得分:0)
在我的情况下,问题是 createCaptureRequest 在另一个已经在进程中被调用多次(onConfigured / onConfigureFailed被调用)。
我最终创建了一个如果camera_preview已在进行中,则保持跟踪的布尔变量,如果是,则不要再创建另一个 createCaptureRequest 。
答案 3 :(得分:0)
检查所有摄像机配置是否已使用标记设置,如@Rohit建议的那样,或者在mCaptureSession的重复请求时给予一些延迟,同时在后台并行设置配置。在我的情况下,我通过延迟500 mS来设置repeatRequest来解决这个异常:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
try {
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(),
mCaptureCallback, null);
} catch (CameraAccessException e) {
Log.e(TAG, "Failed to start camera preview because it couldn't access camera", e);
} catch (IllegalStateException e) {
Log.e(TAG, "Failed to start camera preview.", e);
}
}
}, 500);
此外,当您第一次授予权限并最初启动相机预览(应用程序崩溃)时会出现同样的问题,但在那里您将收到CameraAccessException,说明"无法启动相机会话"。在这种情况下,您应该在创建捕获会话时给出相同的延迟量,如下所示:
void startCaptureSession() {
if (!isCameraOpened() || !mPreview.isReady() || mImageReader == null) {
return;
}
previewSize = chooseOptimalSize();
mPreview.setBufferSize(previewSize.getWidth(), previewSize.getHeight());
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
try {
Surface surface = mPreview.getSurface();
mPreviewRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
mCamera.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
mSessionCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
throw new RuntimeException("Failed to start camera session");
}
}
}, 500);
}
我希望它有所帮助。
答案 4 :(得分:0)
在文档中说:
如果此会话不再有效,则可能是由于该会话已被明确关闭,已创建新会话或已关闭摄像头设备。
如果您使用的是camera2api示例项目,则意味着:您同时调用openCamera()
,createCameraPreviewSession()
或closeCamera()
,也可以调用createCameraPreviewSession()
。
当调用函数createCameraPreviewSession()
时,我用一个始终设置为true的全局变量解决了这个问题;并且设置为false,createCameraPreviewSession()
完成后的10MS。如果此变量为true,则会阻止所有新的createCameraPreviewSession()
调用以及所有closeCamera()
调用。
此解决方案对我有用。但是,我不知道是否有根本原因,为什么不应该使用它。如果有人知道得更多,请告诉我。