8

I am playing with the original example of BarCode scanner here:

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

They are able to start the AutoFocus/Flash within the camera factory like this:

    // Creates and starts the camera.  Note that this uses a higher resolution in comparison
    // to other detection examples to enable the barcode detector to detect small barcodes
    // at long distances.
    CameraSource.Builder builder = new CameraSource.Builder(getApplicationContext(), barcodeDetector)
            .setFacing(CameraSource.CAMERA_FACING_BACK)
            .setRequestedPreviewSize(1600, 1024)
            .setRequestedFps(15.0f);

    // make sure that auto focus is an available option
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        builder = builder.setFocusMode(
                autoFocus ? Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE : null);
    }

    mCameraSource = builder
            .setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null)
            .build();

However this method on cameraSource builder is gone in current version and so this setting cannot be accessed. Also I need to change the FlashMode during usage, so that is not the way to do it either. I found this ugly solution to accessing the camera:

public static Camera getCamera(@NonNull CameraSource cameraSource) {
    Field[] declaredFields = CameraSource.class.getDeclaredFields();

    for (Field field : declaredFields) {
        if (field.getType() == Camera.class) {
            field.setAccessible(true);
            try {
                Camera camera = (Camera) field.get(cameraSource);
                if (camera != null) {
                    return camera;
                }

                return null;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

            break;
        }
    }

    return null;
}

Although it works, it does not help: when calling getParameters().setFocusMode() I am getting this exception:

Attempt to invoke virtual method 'android.hardware.Camera$Parameters android.hardware.Camera.getParameters()' on a null object reference

Obviously what I am doing is not a right way to do it, but there seem to be no documentation about it.

Thanks for hints.

VC.One
  • 14,790
  • 4
  • 25
  • 57
Vojtěch
  • 11,312
  • 31
  • 103
  • 173
  • You could maybe use the custom `CameraSource` from the [mobile-vision codelabs](https://codelabs.developers.google.com/codelabs/mobile-vision-ocr/#4), it has a `setFlashMode()` included – Dan Chaltiel Nov 01 '18 at 10:25

3 Answers3

17

Just optimize your code as following and you have to call this method after building Camera Source class.

private Camera camera = null;
boolean flashmode=false;
private void flashOnButton() {
    camera=getCamera(mCameraSource);
    if (camera != null) {
        try {
            Camera.Parameters param = camera.getParameters();
         param.setFlashMode(!flashmode?Camera.Parameters.FLASH_MODE_TORCH :Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(param);
            flashmode = !flashmode;
            if(flashmode){
                showToast("Flash Switched ON");
            }
            else {
                showToast("Flash Switched Off");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
private static Camera getCamera(@NonNull CameraSource cameraSource) {
    Field[] declaredFields = CameraSource.class.getDeclaredFields();

    for (Field field : declaredFields) {
        if (field.getType() == Camera.class) {
            field.setAccessible(true);
            try {
                Camera camera = (Camera) field.get(cameraSource);
                if (camera != null) {
                    return camera;
                }
                return null;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            break;
        }
    }
    return null;
}

This will help you to enable flash in Google Vision Api using camerasource object.

VivekTamilarasan
  • 379
  • 3
  • 10
0

Here is a working kotlin variant:

private var flashmode: Boolean = false
private var camera: Camera? = null

private fun flashOnButton() {
    camera = getCamera(cameraSource)

    if (camera != null) {
        try {
            val param = camera!!.parameters

            param.setFlashMode(if (!flashmode) Camera.Parameters.FLASH_MODE_TORCH else Camera.Parameters.FLASH_MODE_OFF)
            camera?.parameters = param
            flashmode = !flashmode
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }
}

private fun getCamera(cameraSource: CameraSource): Camera? {
    val declaredFields = CameraSource::class.java.declaredFields

    for (field in declaredFields) {
        if (field.type === Camera::class.java) {
            field.isAccessible = true

            try {
                val camera = field.get(cameraSource) as Camera
                return if (camera != null) {
                    camera
                } else null
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
            }

            break
        }
    }

    return null
}

This solution works for now. But I don't know how to handle this, when android.hardware.Camera is not supported anymore in the future. Maybe there is a better solution without android.hardware.Camera?

teawithfruit
  • 767
  • 1
  • 11
  • 22
-1

Just use the CameraSource directly.

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

And you will have the ability to use flash/focus.

CameraSource
.setFlashMode()
.setFocusMode()
DoronK
  • 4,837
  • 2
  • 32
  • 37