在Android上的“图像捕获”和“视频捕获”之间切换的最佳方法是什么?

问题描述

我正在尝试创建一个可以同时录制视频和拍照的活动。我目前正在使用CameraX API来简化操作,并希望坚持使用它而不是Camera2或其他任何东西。 对于布局,我有两个按钮,一个用于图片,另一个用于视频和TextureView。我的问题是在ImageCapture和VideoCapture对象之间切换的最佳方法是什么?

我必须将它们绑定到活动的生命周期才能使它们起作用,但是一次只能起作用。否则,我会遇到this问题。我试图使按钮为我自己做,但是那需要我在切换Capture对象后更改按钮的功能。我也在考虑使用片段,但是我觉得有一种更简单的方法。如果可能的话,我也希望将按钮合并为一个。

   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(),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,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(),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(),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,vidCap);
    }

同样,我的布局只是顶部的两个按钮和TextureView。您还需要在清单文件中同时具有音频,摄像机和外部存储的写权限,然后在活动中检查它们。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)