Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flashlight control in Marshmallow

I have a problem regarding the camera in the most recent Marshmallow build, more specifically the flashlight. On any pre-Marshmallow version all I need to do to turn the flash on/off was the following:

private void turnFlashOn(final Camera camera, int flashLightDurationMs) {
    if (!isFlashOn()) {
        final List<String> supportedFlashModes = camera.getParameters().getSupportedFlashModes();
        if (supportedFlashModes != null && supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
            mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
            camera.setParameters(mParams);
        }
    }
}

and

private void turnFlashOff(Camera camera) {
    if (camera != null) {
        final List<String> supportedFlashModes = camera.getParameters().getSupportedFlashModes();
        if (supportedFlashModes != null && supportedFlashModes.contains(Camera.Parameters.FLASH_MODE_OFF)) {
            mParams.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(mParams);
        }
    }
}

Unfortunately, Marshmallow devices began to crash in the wild. Somehow camera.getParameters() and camera.setParameters() began to fail with messages such as:

RuntimeException: getParameters failed (empty parameters)

RuntimeException: setParameters failed

I tried starting and stopping the preview before getting the parameters, which no longer throws errors. However the preview is not resumed when I call camera.startPreview().

I fear releasing the camera and reopening it is out of the question as this takes some seconds and would produce a bad experience.

Any suggestions on how to turn the flashlight on/off in Marshmallow reliably?

like image 824
Edson Menegatti Avatar asked Oct 22 '15 14:10

Edson Menegatti


2 Answers

Google has introduced torchmode in OS 6 (Android M).
if your purpose is only to turn on/off the flash, below code can help you with that:

private static void handleActionTurnOnFlashLight(Context context){
    try{

        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        String[] list = manager.getCameraIdList();
        manager.setTorchMode(list[0], true);
    }
    catch (CameraAccessException cae){
        Log.e(TAG, cae.getMessage());
        cae.printStackTrace();
    }
}

private static void handleActionTurnOffFlashLight(Context context){
    try{
        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
        manager.setTorchMode(manager.getCameraIdList()[0], false);
    }
    catch (CameraAccessException cae){
        Log.e(TAG, cae.getMessage());
        cae.printStackTrace();
    }
}

All you have to do is: Get cameraid's list out of which camera ID zero(0) is your primary camera for which you want to turn flash on/off. Simply pass the cameraID to setTochMode API with boolean value for turning it on or off.

Do note that this piece of code will work only with OS 6, so you need to check for device OS and based upon that you need to select which API's to call for pre-marshmallow devices.

Kindly mark this as solution if it solves your problem.

like image 64
Saurabh7474 Avatar answered Nov 16 '22 11:11

Saurabh7474


As Saurabh7474 has responded, to check the version of Android and use setTorchMode API it's very correct.

Although you can also use params.setFlashMode (...) in marshmallow using

mCamera.setPreviewTexture (new SurfaceTexture (100))

after Camera.open (...) and before calling mCamera.startPreview();

try {
                Log.i(TAG, "getCamera");
                int requestedCameraId = getIdForRequestedCamera(mFacing);
                if (requestedCameraId == -1) {
                    throw new RuntimeException("Could not find requested camera.");
                }
                mCamera = Camera.open(requestedCameraId);
                mCamera.setPreviewTexture(new SurfaceTexture(DUMMY_TEXTURE_NAME));
                params = mCamera.getParameters();
            } catch (RuntimeException e) {
                Log.e("Failed to Open. Error:", e.getMessage());
            } catch (IOException e) {
                Log.e("Failed to Open. can't setPreviewTexture:", e.getMessage());
            }

then when you want, you can use

        mParams.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
        camera.setParameters(mParams);

My answer is based on CameraSource examples of Vision API that uses params.setFlashMode (...) and works in Api 23 and above. If you decide to inspect CameraSource, the key method that has solved the same problem is "start ()", in the line 312 ...

https://github.com/googlesamples/android-vision/blob/master/visionSamples/barcode-reader/app/src/main/java/com/google/android/gms/samples/vision/barcodereader/ui/camera/CameraSource.java

The reason you can find here https://stackoverflow.com/a/33333046/4114846

like image 22
yeberiah Avatar answered Nov 16 '22 11:11

yeberiah