Java 在Android上切换图像捕获和视频捕获的最佳方式是什么?
我正在尝试创建一个可以同时录制视频和拍照的活动。我目前正在使用CameraX API,因为它很简单,我希望继续使用它,而不是Camera2或其他任何东西。 对于布局,我有两个按钮,一个用于图片,另一个用于视频和TextureView。我的问题是,在ImageCapture和VideoCapture对象之间切换的最佳方式是什么 我必须将它们绑定到活动的生命周期,以便它们工作,但一次只能有一个。否则,我就有麻烦了。我试图让按钮为我做这件事,但这需要我在切换捕获对象后更改按钮的功能。我也在考虑使用片段,但我觉得有一种更简单的方法。如果可能的话,我也希望将按钮组合成一个Java 在Android上切换图像捕获和视频捕获的最佳方式是什么?,java,android,android-fragments,android-button,android-camerax,Java,Android,Android Fragments,Android Button,Android Camerax,我正在尝试创建一个可以同时录制视频和拍照的活动。我目前正在使用CameraX API,因为它很简单,我希望继续使用它,而不是Camera2或其他任何东西。 对于布局,我有两个按钮,一个用于图片,另一个用于视频和TextureView。我的问题是,在ImageCapture和VideoCapture对象之间切换的最佳方式是什么 我必须将它们绑定到活动的生命周期,以便它们工作,但一次只能有一个。否则,我就有麻烦了。我试图让按钮为我做这件事,但这需要我在切换捕获对象后更改按钮的功能。我也在考虑使用片段
private void startCamera() {
CameraX.unbindAll();
Rational aspectRatio = new Rational(textureView.getWidth(), textureView.getHeight());
Size screen = new Size(textureView.getWidth(), textureView.getHeight());
PreviewConfig pConfig = new PreviewConfig.Builder().setTargetAspectRatio(aspectRatio).setTargetResolution(screen).build();
Preview preview = new Preview(pConfig);
preview.setOnPreviewOutputUpdateListener(new Preview.OnPreviewOutputUpdateListener() {
@Override
public void onUpdated(Preview.PreviewOutput output) {
ViewGroup parent = (ViewGroup) textureView.getParent();
parent.removeView(textureView);
parent.addView(textureView);
textureView.setSurfaceTexture(output.getSurfaceTexture());
updateTransform();
}
});
setupPictures(preview);
setupVideos(preview);
}
private void setupPictures(Preview preview) {
ImageCaptureConfig imageCaptureConfig = new ImageCaptureConfig.Builder().setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY).
setTargetRotation(getWindowManager().getDefaultDisplay().getRotation()).build();
final ImageCapture imgCap = new ImageCapture(imageCaptureConfig);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = new File("/storage/emulated/0/DCIM/Camera/"); //getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image;
try {
image = File.createTempFile(
imageFileName, //
".jpg", //
storageDir // directory
);
imgCap.takePicture(image, new ImageCapture.OnImageSavedListener() {
@Override
public void onImageSaved(@NonNull File file) {
String msg = "Pic capture at " + file.getAbsolutePath();
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onError(@NonNull ImageCapture.UseCaseError useCaseError, @NonNull String message, @Nullable Throwable cause) {
String msg = "Pic Capture failed: " + message;
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
if (cause != null) {
cause.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
CameraX.bindToLifecycle(this, preview, imgCap); // I want this to be triggered by one of the
// two buttons and same with the other
// but buttons also need to take pic or vid
}
private void setupVideos(Preview preview) {
VideoCaptureConfig videoCaptureConfig = new VideoCaptureConfig.Builder().
setLensFacing(CameraX.LensFacing.BACK).
setTargetRotation(getWindowManager().getDefaultDisplay().getRotation()).build();
final boolean[] recording = new boolean[]{false};
@SuppressLint("RestrictedApi")
final VideoCapture vidCap = new VideoCapture(videoCaptureConfig);
CameraX.bindToLifecycle(this, preview, vidCap);
findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
@SuppressLint("RestrictedApi")
@Override
public void onClick(View v) {
if (!recording[0]) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "MP4_" + timeStamp + "_";
File storageDir = new File("/storage/emulated/0/DCIM/Camera/"); //getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File video;
try {
video = File.createTempFile(
imageFileName, /* prefix */
".mp4", /* suffix */
storageDir /* directory */
);
vidCap.startRecording(video, new VideoCapture.OnVideoSavedListener() {
@Override
public void onVideoSaved(File file) {
String msg = "Vid capture at " + file.getAbsolutePath();
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onError(VideoCapture.UseCaseError useCaseError, String message, @Nullable Throwable cause) {
String msg = "Vid Capture failed: " + message;
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
if (cause != null) {
cause.printStackTrace();
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
recording[0] = true;
} else {
vidCap.stopRecording();
recording[0] = false;
}
}
});
CameraX.bindToLifecycle(this, preview, vidCap);
}
同样,我的布局只是顶部的两个按钮和TextureView。您还需要对清单文件中的音频、摄像头和外部存储写入权限,然后在活动中检查它们。因此我决定使用片段来尝试解决我的问题,但现在我遇到的问题是,当我在视频片段和图片片段之间来回切换时,负责连接到PictureCapture或VideoCapture到实际“相机”和纹理的线程无法正确断开和重新连接片段。我不确定这是否真的发生了,但我目前没有任何其他想法。因此我决定使用片段来解决我的问题,但现在我遇到的问题是,当我在视频片段和图片片段之间来回切换时,负责连接到PictureCapture或VideoCapture到实际“相机”和纹理的线程无法正确断开和重新连接片段。我不确定这是否真的发生了,但我目前没有任何其他想法