Turning on/off flash with Android camera2 API not working

折月煮酒 提交于 2020-06-10 05:19:58

问题


I'm creating an Android app with a custom camera and I'm switching to the new camera2 API. I have a button allowing to turn ON and OFF the flash when the back camera is on (without stopping the camera, like any classic camera app).

When I tap the flash icon, nothing happens and this is what the logcat returns:

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

I don't know why it's not working. Here is the code:

I have a RecordVideoActivity using a RecordVideoFragment. Here is the fragment's XML part that contains the flash button code:

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

And the Java code:

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

With in the 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();
        }
    });

And here is the actionFlash() function definition:

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

Any idea what could be wrong?

(I already looked at this question but it doesn't address my problem)

Thank you very much for your help. This is driving me crazy.


回答1:


Create these variables:

    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;

then add these methods:

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);
    }
}

after this line add this code:

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

setupFlashButton();

at the end call switchFlash() in your desired click listener.

et voilà!

PS. This might be helpful - front/back camera switcher




回答2:


The problem with your code is "mCameraManager.setTorchMode(mCameraId, true);" This call requires API 23+. Hence, You can not call this native method from APIs lower than API 23. What you could do is use Depricated Camera API. It works for all devices and will keep on working for quite sometime in near future. Here is what you could do, add this code using if-else statements. If device is API23+, use Camera2 otherwise use Camera. That's what I do.

Add hardware.Camera in your imports

import android.hardware.Camera;

Initialize variables

Camera camera;
Camera.Parameters params;

Now, Get the Camera and turn on the flash

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

And you are good to go.



来源:https://stackoverflow.com/questions/38695149/turning-on-off-flash-with-android-camera2-api-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!