CameraX ImageCapture jpeg回调超时



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

误差

这是一个片段,其中相机代码被称为

@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);
});
}

}

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

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

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

我对你的代码还有两点意见。

  1. 您为测试目的添加的代码(您在10秒后安排图像捕获)应该仅在相机设置工作时执行。例如,您可以在调用bindToLifecycle()之后运行它。

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

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

最新更新