【问题标题】:CameraX ImageCapture Hit timeout for jpeg callbackCameraX ImageCapture Hit timeout for jpeg 回调
【发布时间】:2021-02-19 09:01:54
【问题描述】:

我正在尝试按照https://developer.android.com/training/camerax/take-photo 实现图像捕获,我在 Temi Robot 上运行我的设备,预览似乎工作正常,但我遇到了这个错误,当我尝试执行回调时没有执行捕捉图像。

Error

这是调用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);
    });
}

}

【问题讨论】:

    标签: java android android-camerax


    【解决方案1】:

    您无法拍照,因为ImageCapture 设置不正确,您在调用ProcessCameraProvider.bindToLifecycle() 时未绑定它。你应该这样写:

    Preview preview = ...;
    preview.setSurfaceProvider(...);
    
    ImageCapture imageCapture = ...;
    
    // bind both preview and imageCapture
    cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageCapture);
    

    这将(应该)允许对takePicture() 的调用成功。

    我还有另外 2 个关于你的代码的 cmets。

    1. 您为测试目的添加的代码(您安排在 10 秒后拍摄图像)应仅在相机设置有效的情况下执行。例如,您可以在调用 bindToLifecycle() 之后运行它。

    2. 将用例绑定到片段 Activity 的生命周期可能不是一个好主意。 bindToLifecycle(LifecycleOwner, ...) 中的生命周期所有者控制相机何时打开和关闭,因此您通常希望在片段或其视图启动时启动相机,并在片段或其视图停止时停止相机。由于您正在显示预览,因此您可以将相机的打开/关闭与片段视图的生命周期联系起来,因此您可以编写:

    cameraProvider.bindToLifecycle(getViewLifecycleOwner(), cameraSelector, preview, imageCapture);
    

    【讨论】:

    • 我想你错过了我绑定 ImageCapture 的部分,因为它被屏幕截断了,但是 imageCapture 已经包含在 bindToLifecycle 方法中,该方法在 bindPreview 方法中调用onViewCreated我已按照您的建议更改了生命周期所有者。
    • 啊,我的错,我错过了绑定图像捕获用例的部分。您能否在其他设备上重现此问题?您是否在运行其他相机应用程序的 Temi 机器人上遇到此问题,例如camera2 示例应用程序。
    • 我最初使用的是已弃用的相机库,预览和图像捕获工作正常,但存在一个问题,即捕获的图像旋转 180 度,我找不到解决该问题的方法,所以我决定尝试camerax。我还没有尝试在其他设备上运行该应用程序/尝试使用 camera2 示例应用程序,但到目前为止,camerax 预览工作正常。
    • 更新:我已经从github.com/android/camera-samples 测试了CameraXBasic 和Camera2Basic,并且都在Temi 机器人上工作,似乎都可以工作!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-23
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多