使用Android camera2 API打开/关闭闪光灯无法正常工作

时间:2016-08-01 09:20:13

标签: android camera android-camera2 camera2

我正在使用自定义相机创建Android应用,并且我正在切换到新的camera2 API。我有一个按钮,可以在后置摄像头开启时打开和关闭闪光灯(不像任何经典的相机应用程序那样停止摄像头)。

当我点击flash图标时,没有任何反应,这就是logcat返回的内容:

D/ViewRootImpl: ViewPostImeInputStage processPointer 0
D/ViewRootImpl: ViewPostImeInputStage processPointer 1

我不知道为什么它不起作用。这是代码:

我使用RecordVideoActivity RecordVideoFragment。以下是片段的XML部分,其中包含flash按钮代码:

<ImageButton
    android:id="@+id/button_flash"
    android:src="@drawable/ic_flash_off"
    android:layout_alignParentLeft="true"
    style="@style/actions_icons_camera"
    android:onClick="actionFlash"/>

Java代码:

ImageButton flashButton;
private boolean hasFlash;
private boolean isFlashOn = false;

使用onViewCreated

@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
    ...
    [some code]
    ...
    // Flash on/off button
    flashButton = (ImageButton) view.findViewById(R.id.button_flash);
    // Listener for Flash on/off button
    flashButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            actionFlash();
        }
    });

这是actionFlash()函数定义:

private void  actionFlash() {

    /* First check if device is supporting flashlight or not */
    hasFlash = getActivity().getApplicationContext().getPackageManager()
            .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);

    if (!hasFlash) {
        // device doesn't support flash
        // Show alert message and close the application
        AlertDialog alert = new AlertDialog.Builder(this.getActivity())
                .create();
        alert.setMessage("Sorry, your device doesn't support flash light!");
        alert.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        alert.show();
        return;
    }
    else {  // the device support flash
        CameraManager mCameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
        try {
            String mCameraId = mCameraManager.getCameraIdList()[0];
            if (mCameraId.equals("1")) {    // currently on back camera
                if (!isFlashOn) {  // if flash light was OFF
                    // Turn ON flash light
                    try {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            mCameraManager.setTorchMode(mCameraId, true);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // Change isFlashOn boolean value
                    isFlashOn = true;
                    // Change button icon
                    flashButton.setImageResource(R.drawable.ic_flash_off);

                } else { // if flash light was ON
                    // Turn OFF flash light
                    try {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            mCameraManager.setTorchMode(mCameraId, false);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // Change isFlashOn boolean value
                    isFlashOn = false;
                    // Change button icon
                    flashButton.setImageResource(R.drawable.ic_flash_on);
                }
            }
        } catch (CameraAccessException e) {
            Toast.makeText(getActivity(), "Cannot access the camera.", Toast.LENGTH_SHORT).show();
            getActivity().finish();
        }
    }
}

知道可能出现什么问题吗?

(我已经查看了this question,但它没有解决我的问题)

非常感谢你的帮助。这让我发疯了。

5 个答案:

答案 0 :(得分:12)

创建这些变量:

    public static final String CAMERA_FRONT = "1";
    public static final String CAMERA_BACK = "0";

    private String cameraId = CAMERA_BACK;
    private boolean isFlashSupported;
    private boolean isTorchOn;

然后添加以下方法:

public void switchFlash() {
    try {
        if (cameraId.equals(CAMERA_BACK)) {
            if (isFlashSupported) {
                if (isTorchOn) {
                    mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
                    mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
                    flashButton.setImageResource(R.drawable.ic_flash_off);
                    isTorchOn = false;
                } else {
                    mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
                    mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
                    flashButton.setImageResource(R.drawable.ic_flash_on);
                    isTorchOn = true;
                }
            }
        }
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

public void setupFlashButton() {
    if (cameraId.equals(CAMERA_BACK) && isFlashSupported) {
        flashButton.setVisibility(View.VISIBLE);

        if (isTorchOn) {
            flashButton.setImageResource(R.drawable.ic_flash_off);
        } else {
            flashButton.setImageResource(R.drawable.ic_flash_on);
        }

    } else {
        flashButton.setVisibility(View.GONE);
    }
}

在此line之后添加此代码:

Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
isFlashSupported = available == null ? false : available;

setupFlashButton();

最后在您想要的点击监听器中调用 switchFlash()

etvoilà!

PS。这可能会有所帮助 - front/back camera switcher

答案 1 :(得分:1)

@MrOnyszko的回答是正确的,但需要更新为

isTorchAvailable = camChars.get(CameraCharacteristics.FLASH_INFO_AVAILABLE).booleanValue();
CameraManager camManager = (CameraManager).context.getSystemService(Context.CAMERA_SERVICE);
          
try {
    String cameraId cameraId = camManager.getCameraIdList()[0];
    CameraCharacteristics camChars = camManager.getCameraCharacteristics(cameraId);

    boolean isTorchAvailable = camChars.get(CameraCharacteristics.FLASH_INFO_AVAILABLE).booleanValue();
    if(isTorchAvailable) {
        camManager.setTorchMode(cameraId, true);   //Turn ON
        camManager.setTorchMode(cameraId, false);
    }
} catch (CameraAccessException e) {
    e.printStackTrace();
}

答案 2 :(得分:0)

我看到对于 cameraX,ImageCapture.flashMode 仅在我们使用初始配置、ImageCapture.Builder() 等构建时有效。 但是如果你想动态启用/禁用 flash,你就必须使用下面的。

camera?.cameraControl?.enableTorch(enableFlash)

如果您想知道什么是相机?从文档中捕获。

// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture
)

答案 3 :(得分:-2)

您的代码存在问题“ mCameraManager.setTorchMode(mCameraId,true) ;;” 此调用需要API 23+。因此,您不能从低于API 23的API调用此本机方法。 你可以做的是使用Depricated Camera API。它适用于所有设备,并将在不久的将来继续工作。 这是您可以做的,使用if-else语句添加此代码。如果设备是API23 +,请使用Camera2否则使用Camera。这就是我的工作。

在导入中添加hardware.Camera

import android.hardware.Camera;

初始化变量

Camera camera;
Camera.Parameters params;

现在,拿到相机并开启闪光灯

try {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
       mCameraManager.setTorchMode(CameraId, true);
     } 
else {
camera = Camera.open();
params = camera.getParameters();
params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(params);
camera.startPreview();
}
catch (Exception e) 
{
 e.printStackTrace();
  }

你很高兴。

答案 4 :(得分:-2)

您使用的逻辑不向后兼容,我还验证了它即使在23+的某些设备上也无法使用,最好使用Camera Manager API(支持21+的版本)

Date

请参阅接受的答案以获取详细信息