CameraX ImageCapture Время ожидания для обратного вызова jpeg

#java #android #android-camerax

#java #Android #android-camerax

Вопрос:

Я пытаюсь реализовать захват изображения в соответствии с https://developer.android.com/training/camerax/take-photo , Я запускаю свое устройство на Temi Robot, предварительный просмотр, кажется, работает нормально, но я сталкиваюсь с этой ошибкой, и обратный вызов не выполняется, когда я пытаюсь захватить изображение.

Ошибка

Это фрагмент, в котором вызывается код camerax

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    viewModel = new ViewModelProvider(getActivity()).get(GlobalViewModel.class);
    cameraProviderFuture = ProcessCameraProvider.getInstance(getContext());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.patrol_fragment, container, false);
}

    @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    previewView = view.findViewById(R.id.previewView);
    cameraProviderFuture.addListener(() -> {
        try {
            ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
            bindPreview(cameraProvider, view);
        } catch (ExecutionException | InterruptedException e) {
            Log.e(TAG, "CameraProvider initialization error: "   e.toString());
        }
    }, ContextCompat.getMainExecutor(getContext()));
         Just for testing
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                takePicture();
            }
        }, 10000);
}

private void bindPreview(ProcessCameraProvider cameraProvider, View view) {
    Preview preview = new Preview.Builder().build();
    CameraSelector cameraSelector = new CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
            .build();

    preview.setSurfaceProvider(previewView.getSurfaceProvider());

    imageCapture = new ImageCapture.Builder()
            .setTargetRotation(view.getDisplay().getRotation())
            .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
            .build();

    Camera camera = cameraProvider.bindToLifecycle(getActivity(), cameraSelector, imageCapture,
            preview);

    takePicture();

}

private void takePicture() {
    File mediaFile = getMediaFile();

    ImageCapture.OutputFileOptions outputFileOptions =
            new ImageCapture.OutputFileOptions.Builder(mediaFile).build();
    imageCapture.takePicture(outputFileOptions, viewModel.getExecutorService(),
            new ImageCapture.OnImageSavedCallback() {
                @Override
                public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) {
                    // insert your code here.
                    Log.i(TAG, "Capture success!");
                }

                @Override
                public void onError(ImageCaptureException error) {
                    // insert your code here.
                    Log.e(TAG, "Capture failed :( "   error.toString());

                }
            }
    );
}

private File getMediaFile() {
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "TemiPatrol");
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d(TAG, "failed to create directory");
            return null;
        }
    }
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    return new File(mediaStorageDir.getPath()   File.separator  
            "IMG_"  timeStamp   ".jpg");
}

private void sendImageToServer(JSONObject requestJson) {
    // for testing
    viewModel.getExecutorService().execute(() -> {
        JsonPostman postman = new JsonPostman(getActivity());
        postman.postRequest(requestJson);
    });
}
 

}

Ответ №1:

Вы не можете делать снимки, потому ImageCapture что не был настроен правильно, вы не привязываете его при вызове ProcessCameraProvider.bindToLifecycle() . Вы должны написать что-то вроде этого:

 Preview preview = ...;
preview.setSurfaceProvider(...);

ImageCapture imageCapture = ...;

// bind both preview and imageCapture
cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageCapture);
 

Это позволит (должно) разрешить takePicture() успешные вызовы.

У меня есть еще 2 комментария к вашему коду.

  1. Код, который вы добавили в целях тестирования (где вы планируете захват изображения через 10 секунд), должен выполняться только в том случае, если настройка камеры работает. Вы могли бы запустить его после вызова bindToLifecycle() , например.
  2. Привязка вариантов использования к жизненному циклу действия фрагмента, вероятно, не очень хорошая идея. Владелец жизненного цикла в bindToLifecycle(LifecycleOwner, ...) управляет открытием и закрытием камеры, поэтому обычно требуется, чтобы камера запускалась при запуске фрагмента или его просмотра, и останавливалась при остановке фрагмента или его просмотра. Поскольку вы отображаете предварительный просмотр, вы можете привязать открытие / закрытие камеры к жизненному циклу просмотра фрагмента, чтобы вы могли писать:
 cameraProvider.bindToLifecycle(getViewLifecycleOwner(), cameraSelector, preview, imageCapture);
 

Комментарии:

1. Я думаю, вы пропустили ту часть, где я привязал ImageCapture, поскольку он был отключен экраном, но ImageCapture уже был включен в bindToLifecycle метод, который был вызван в bindPreview методе в onViewCreated Я изменил владельца жизненного цикла, как вы предложили.

2. Ах, мой плохой, я пропустил ту часть, где вы привязываете вариант использования захвата изображения. Можете ли вы воспроизвести эту проблему на других устройствах? И сталкиваетесь ли вы с этой проблемой на роботе Temi, в котором запущены другие приложения для камеры, например, пример приложения camera2.

3. Изначально я использовал устаревшую библиотеку камер, предварительный просмотр и захват изображений работали нормально, но возникла проблема, из-за которой захваченные изображения поворачивались на 180 градусов, и я не мог найти способ решить эту проблему, поэтому я решил попробовать camerax. Мне еще предстоит попытаться запустить приложение на других устройствах / попробовать пример приложения camera2, но пока предварительный просмотр camerax работает нормально.

4. Обновление: с тех пор я протестировал CameraXBasic и Camera2Basic из github.com/android/camera-samples и оба, начиная с работы над роботом Temi, оба, кажется, работают!