Я использую Camera2API для создания активности камеры, которая отправляет снятые изображения по электронной почте, но я получаю эту ошибку. На устройствах Samsung
java .lang.IllegalStateException, которое говорит: «Сессия была закрыта; далее изменения незаконны ". в CameraHandler.takePicture
Есть предложения? что-нибудь еще, я должен обработать?, который я не сделал?
У меня нет большого опыта с Camera2API. Большое спасибо людям, готовым помочь!
Fatal Exception: java.lang.IllegalStateException: CameraDevice was already closed
at android.hardware.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:1986)
at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:857)
at android.hardware.camera2.impl.CameraDeviceImpl.capture(CameraDeviceImpl.java:754)
at android.hardware.camera2.impl.CameraCaptureSessionImpl.capture(CameraCaptureSessionImpl.java:179)
at houssamos.eyes.catcher.custom.CameraHandler.takePicture(CameraHandler.java:292)
at houssamos.eyes.catcher.services.CameraService.lambda$onCameraReady$0(CameraService.java:79)
at houssamos.eyes.catcher.services.-$$Lambda$CameraService$oty1Y9969dtGOUT0_Xh3u3QNQd0.run(lambda)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
и это мой класс CameraHandler
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class CameraHandler {
private static final String TAG = CameraHandler.class.getSimpleName();
public interface Callback {
void onCameraReady();
void onPicture(Image image);
void onError(String message);
void onCameraDisconnected();
}
private class CompareSizesByArea implements Comparator<Size> {
@Override
public int compare(Size lhs, Size rhs) {
return Long.signum((long) lhs.getWidth() * lhs.getHeight()
- (long) rhs.getWidth() * rhs.getHeight());
}
}
private Callback cameraCallback;
private String currentCamera;
private SurfaceTexture surfaceTexture;
private CameraManager cameraManager;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSession;
private CameraCharacteristics cameraCharacteristics;
private CaptureRequest.Builder previewRequestBuilder;
private CaptureRequest.Builder captureRequestBuilder;
private ImageReader imageReader;
public CameraHandler(Context context) {
if ((context instanceof Callback))
this.cameraCallback = (Callback) context;
else {
notifyError("Provided context must implement CameraHandler.Callback");
return;
}
this.cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) {
notifyError("You don't have the required permissions.");
return;
}
//select camera
SparseArray<String> camerasList = getCamerasList();
if (camerasList == null) {
notifyError("No camera detected");
return;
}
currentCamera = camerasList.get(CameraCharacteristics.LENS_FACING_FRONT);
if (currentCamera == null) {
notifyError("No front camera detected");
return;
}
Log.i(TAG, "Camera id: " + currentCamera);
try {
cameraCharacteristics = cameraManager.getCameraCharacteristics(currentCamera);
StreamConfigurationMap map = cameraCharacteristics
.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (map != null) {
Size previewSize = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
new CompareSizesByArea());
imageReader = ImageReader.newInstance(previewSize.getWidth(), previewSize.getHeight(),
ImageFormat.JPEG, 1);
ImageReader.OnImageAvailableListener onImageAvailable = reader -> {
if (cameraCallback != null) {
cameraCallback.onPicture(imageReader.acquireLatestImage());
}
};
imageReader.setOnImageAvailableListener(onImageAvailable, null);
} else {
notifyError("Could not get configuration map.");
}
} catch (CameraAccessException e) {
notifyError(e.getMessage());
}
}
@SuppressLint("MissingPermission")
public void capture() {
//open camera
try {
cameraManager.openCamera(currentCamera, new CameraDevice.StateCallback() {
@Override
public void onOpened(@NonNull CameraDevice camera) {
cameraDevice = camera;
setupPreview(CameraDevice.TEMPLATE_STILL_CAPTURE);
// setupPreview(CameraDevice.TEMPLATE_PREVIEW);
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {
if (cameraCallback != null) {
cameraCallback.onError("Camera device is no longer available for use.");
cameraCallback.onCameraDisconnected();
}
}
@Override
public void onError(@NonNull CameraDevice camera, int error) {
switch (error) {
case CameraDevice.StateCallback.ERROR_CAMERA_DEVICE:
notifyError("Camera device has encountered a fatal error.");
break;
case CameraDevice.StateCallback.ERROR_CAMERA_DISABLED:
notifyError("Camera device could not be opened due to a device policy.");
break;
case CameraDevice.StateCallback.ERROR_CAMERA_IN_USE:
notifyError("Camera device is in use already.");
break;
case CameraDevice.StateCallback.ERROR_CAMERA_SERVICE:
notifyError("Camera service has encountered a fatal error.");
break;
case CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE:
notifyError("Camera device could not be opened because there are too many other open camera devices.");
break;
}
}
}, null);
} catch (CameraAccessException e) {
notifyError(e.getMessage());
}
}
/**
* Get available cameras
*
* @return SparseArray of available cameras ids
*/
private SparseArray<String> getCamerasList() {
SparseArray<String> camerasList = new SparseArray<>();
try {
String[] camerasAvailable = cameraManager.getCameraIdList();
CameraCharacteristics cam;
Integer characteristic;
for (String id : camerasAvailable) {
cam = cameraManager.getCameraCharacteristics(id);
characteristic = cam.get(CameraCharacteristics.LENS_FACING);
if (characteristic != null) {
switch (characteristic) {
case CameraCharacteristics.LENS_FACING_FRONT:
camerasList.put(CameraCharacteristics.LENS_FACING_FRONT, id);
break;
case CameraCharacteristics.LENS_FACING_BACK:
camerasList.put(CameraCharacteristics.LENS_FACING_BACK, id);
break;
case CameraCharacteristics.LENS_FACING_EXTERNAL:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
camerasList.put(CameraCharacteristics.LENS_FACING_EXTERNAL, id);
}
break;
}
}
}
return camerasList;
} catch (CameraAccessException e) {
notifyError(e.getMessage());
return null;
}
}
private void setupPreview(int templateType) {
surfaceTexture = new SurfaceTexture(1);
Surface surface = new Surface(surfaceTexture);
try {
previewRequestBuilder = cameraDevice.createCaptureRequest(templateType);
previewRequestBuilder.addTarget(surface);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureRequestBuilder.addTarget(imageReader.getSurface());
cameraDevice.createCaptureSession(Arrays.asList(surface, imageReader.getSurface()),
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
Range<Integer> range = getRange();
previewRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, range);
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, range);
cameraCaptureSession = session;
if (cameraCallback != null) {
cameraCallback.onCameraReady();
}
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
notifyError("Could not configure capture session.");
}
}, null);
} catch (CameraAccessException e) {
notifyError(e.getMessage());
}
}
/**
* Set CaptureRequest parameters for preview e.g. flash, auto-focus, macro mode, etc.
*
* @param key e.g. CaptureRequest.CONTROL_EFFECT_MODE
* @param value e.g. CameraMetadata.CONTROL_EFFECT_MODE_NEGATIVE
*/
public <T> void setCaptureSetting(CaptureRequest.Key<T> key, T value) {
if (captureRequestBuilder != null) {
captureRequestBuilder.set(key, value);
}
}
/**
* start the preview, capture request is built at each call here
*/
public void startPreview() {
try {
cameraCaptureSession.setRepeatingRequest(previewRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
notifyError(e.getMessage());
}
}
/**
* stop the preview
*/
public void stopPreview() {
try {
cameraCaptureSession.stopRepeating();
} catch (CameraAccessException e) {
notifyError(e.getMessage());
} catch (IllegalStateException ignore) {
}
}
/**
* close the camera definitively
*/
public void close() {
surfaceTexture.release();
cameraDevice.close();
}
/**
* take a picture
*/
public void takePicture() {
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION,
cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION));
try {
cameraCaptureSession.capture(captureRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
notifyError(e.getMessage());
}
}
private void notifyError(String message) {
if (cameraCallback != null) {
cameraCallback.onError(message);
}
}
private Range<Integer> getRange() {
try {
CameraCharacteristics chars = cameraManager.getCameraCharacteristics(currentCamera);
Range<Integer>[] ranges = chars.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
Range<Integer> result = null;
for (Range<Integer> range : ranges) {
int upper = range.getUpper();
// 10 - min range upper for my needs
if (upper >= 10) {
if (result == null || upper < result.getUpper()) {
result = range;
}
}
}
if (result == null) {
result = ranges[0];
}
return result;
} catch (CameraAccessException e) {
e.printStackTrace();
return null;
}
}
}