Сессия была закрыта; дальнейшие изменения незаконны Camera2API устройства Samsung - PullRequest
0 голосов
/ 22 апреля 2020

Я использую 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;
      }
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...