为什么打开闪光灯会改变相机的对焦模式?

时间:2019-06-11 08:37:30

标签: java android android-camera2

我有2个AF对焦距离,可以通过按钮和一个用于闪光灯的On Off开关进行控制。

为什么updatePreview()中的flashligh的IF ELSE会影响自动对焦模式?当我注释掉该部分(如果为flashligh为IF ELSE)时,自动对焦模式和对焦距离可与btnFocus正常工作。

如何解决此问题同时仍可以允许用户打开和关闭手电筒?

    private float focusDistance = 0;
    private int flashSwitch = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textureView = (TextureView)findViewById(R.id.textureView);
        //From Java 1.4 , you can use keyword 'assert' to check expression true or false
        assert textureView != null;
        textureView.setSurfaceTextureListener(textureListener);
        btnFocus = (Button)findViewById(R.id.btnFocus);
        btnFlash = (Button)findViewById(R.id.btnFlash);
        btnFocus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                changeFocus();
            }
        });
        btnFlash.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                Flash();
            }
        });
    }

    private void Flash() {
        if(cameraDevice == null)
            return;
        if(flashSwitch == 0 ) {
            Toast.makeText(MainActivity.this, "Flash Turn On ", Toast.LENGTH_SHORT).show();
            flashSwitch = 1;
        }
        else{
            Toast.makeText(MainActivity.this, "Flash Turn Off ", Toast.LENGTH_SHORT).show();
            flashSwitch = 0;
        }
        createCameraPreview();
    }


    private void changeFocus() {
        if(cameraDevice == null)
            return;
        if(focusDistance == 0 )
            focusDistance = 10;
        else
            focusDistance = 0;
        Toast.makeText(MainActivity.this, "Focus Change "+ focusDistance, Toast.LENGTH_SHORT).show();
        createCameraPreview();
    }

    private void createCameraPreview() {
        try{
            SurfaceTexture texture = textureView.getSurfaceTexture();
            assert  texture != null;
            texture.setDefaultBufferSize(imageDimension.getWidth(),imageDimension.getHeight());
            Surface surface = new Surface(texture);
            captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            captureRequestBuilder.addTarget(surface);
            cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                    if(cameraDevice == null)
                        return;
                    cameraCaptureSessions = cameraCaptureSession;
                    updatePreview();
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                    Toast.makeText(MainActivity.this, "Changed", Toast.LENGTH_SHORT).show();
                }
            },null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

如果您取消注释,打开闪光灯并更改焦点时将出现问题。

    private void updatePreview() {
        if(cameraDevice == null)
            Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
        try{
//            if you uncomment this part the problem will come out 
//            if(flashSwitch == 0){
//                captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
//            }
//            else{
//                captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
//            }
            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_OFF);
            captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);
            cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

预期产量

可以在不影响对焦模式的情况下手动打开和关闭闪光灯。

2 个答案:

答案 0 :(得分:0)

updatePreview()中,您要向cameraCaptureSessions发送多个捕获请求,然后再设置captureRequestBuilder中的所有键。首先尝试设置所有键,然后发送一个重复的捕获请求。

private void updatePreview() {
        if(cameraDevice == null)
            Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
        try{
            if(flashSwitch == 0){
                captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
            }
            else{
                captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
            }
            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_OFF);
            captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);

            cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

答案 1 :(得分:0)

我认为您的问题可能出在设置请求的方式上。 您应该首先创建预览,并且只能按照自己的方式创建一次,每次切换闪光灯和/或对焦时都将创建预览。 我建议在onStart中创建预览,并使用以下默认设置:

focusDistance = 0;
flashSwitch = CaptureRequest.FLASH_MODE_OFF;

然后在Flash()和changeFocus()中,而不是通过调用createCameraPreview()来调用updatePreview(),更新预览将如下所示:

private void updatePreview() {
        if(cameraDevice == null)
            Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
        try{
            captureRequestBuilder.set(CaptureRequest.FLASH_MODE, flashSwitch);
            captureRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, focusDistance);    
            cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(),null,mBackgroundHandler);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }