Java 在Android上切换图像捕获和视频捕获的最佳方式是什么?

Java 在Android上切换图像捕获和视频捕获的最佳方式是什么?,java,android,android-fragments,android-button,android-camerax,Java,Android,Android Fragments,Android Button,Android Camerax,我正在尝试创建一个可以同时录制视频和拍照的活动。我目前正在使用CameraX API,因为它很简单,我希望继续使用它,而不是Camera2或其他任何东西。 对于布局,我有两个按钮,一个用于图片,另一个用于视频和TextureView。我的问题是,在ImageCapture和VideoCapture对象之间切换的最佳方式是什么 我必须将它们绑定到活动的生命周期,以便它们工作,但一次只能有一个。否则,我就有麻烦了。我试图让按钮为我做这件事,但这需要我在切换捕获对象后更改按钮的功能。我也在考虑使用片段

我正在尝试创建一个可以同时录制视频和拍照的活动。我目前正在使用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到实际“相机”和纹理的线程无法正确断开和重新连接片段。我不确定这是否真的发生了,但我目前没有任何其他想法