36

I am developing a feature with the possibility of switching the torch into ON/OFF states. Some days ago, we saw a new library from Google in io2019. I came up with an idea, why not use it.

After some time, I don't see any possibilities to use the only torch from the library.

Even in the official documentation, I wasn't able to find any good pieces of information for me, what's more, the sample app from their also don't have to handle my case.

Do you have something in mind what is easy to implement or perhaps you know how to do it with CameraX?

I am worried about using camera or camera2 because the amount of code to be paste is terrible.

Links:

[1] https://developer.android.com/training/camerax

[2] https://proandroiddev.com/android-camerax-preview-analyze-capture-1b3f403a9395

[3] https://github.com/android/camera/tree/master/CameraXBasic

[4] https://github.com/android/camera/tree/master/CameraXBasic

CameraX is an Android Jetpack library that was built with the intent to make camera development easier.

Kewin Czupryński
  • 443
  • 1
  • 5
  • 8

10 Answers10

30
androidx.camera:camera-core:1.0.0-alpha10

You can check is torch available or not with this:

val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageAnalyzer)

camera.cameraInfo.hasFlashUnit()

And you can enable torch with:

camera.cameraControl.enableTorch(true)
murgupluoglu
  • 6,524
  • 4
  • 33
  • 43
18

2021 syntax.

Turn on torch on Android, using Java.

Your typical camera preview code (such as from the google example) generally ends like this:

cameraProvider.bindToLifecycle((LifecycleOwner)this,
                 cameraSelector, imageAnalysis, preview);

to turn on/off the torch...

Camera cam = cameraProvider.bindToLifecycle((LifecycleOwner)this,
                 cameraSelector, imageAnalysis, preview);

if ( cam.getCameraInfo().hasFlashUnit() ) {
    cam.getCameraControl().enableTorch(true); // or false
}

and that's it!

Fattie
  • 27,874
  • 70
  • 431
  • 719
15

2022 Syntax

imageCapture = ImageCapture.Builder()
                .setFlashMode(ImageCapture.FLASH_MODE_ON)
                    .build()


val camera = cameraProvider.bindToLifecycle(
             this, cameraSelector, preview, imageCapture, imageAnalyzer)
                
if (camera.cameraInfo.hasFlashUnit()) {
     camera.cameraControl.enableTorch(true)
}

Mehran Jalili
  • 585
  • 7
  • 18
  • Make sure you're using at least version `'1.2.0-alpha04'` in your gradle.build file and this should lead you to success, young Padawan. – Grant Jan 11 '23 at 08:12
13

This is one way you can do it (Kotlin). If there is a better way please let me know. Following code assumes you have already established the availability of flash on the device.

Declare a flashMode var

private var flashMode: Int = ImageCapture.FLASH_MODE_OFF

In updateCameraUI set a listener

controls.findViewById<ImageButton>(R.id.flash_button).setOnClickListener {
    when (flashMode) {
        ImageCapture.FLASH_MODE_OFF ->
            flashMode = ImageCapture.FLASH_MODE_ON
        ImageCapture.FLASH_MODE_ON ->
            flashMode = ImageCapture.FLASH_MODE_AUTO
        ImageCapture.FLASH_MODE_AUTO ->
            flashMode = ImageCapture.FLASH_MODE_OFF
    }
    // Re-bind use cases to include changes
    bindCameraUseCases()
}

In bindCameraUseCases set the flash mode

            imageCapture = ImageCapture.Builder()
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                .setTargetAspectRatio(screenAspectRatio)
                .setTargetResolution(screenSize)
                .setTargetRotation(rotation)
                .setFlashMode(flashMode)
                .build()
Knight Forked
  • 1,529
  • 12
  • 14
9

I can't comment so I'm answering to expand on yevhen_69's answer.

Setting enabledTorch(true) didn't work for me either, however I found I had to set enableTorch(true) after the call to CameraX.bindToLifecycle

val previewConfig = PreviewConfig.Builder().apply {
        setLensFacing(lensFacing)
        // Any setup
        setTargetRotation(viewFinder.display.rotation)
}.build()

val preview = Preview(previewConfig)

CameraX.bindToLifecycle(this, preview)
preview.enableTorch(true)

However on a side note, CameraX is still in Alpha so its advisable still to use Camera2 API.

Iain Stanford
  • 606
  • 1
  • 6
  • 18
9
// CameraX
def cameraXVersion = "1.0.0-beta07"
implementation "androidx.camera:camera-camera2:$cameraXVersion"
implementation "androidx.camera:camera-lifecycle:$cameraXVersion"
implementation "androidx.camera:camera-view:1.0.0-alpha14"

    private fun initializeFlashButton() = with(binding) {
        camera?.apply {
            if (cameraInfo.hasFlashUnit()) {
                flashButton.setOnClickListener {
                    flashButton.visibility = View.VISIBLE
                    cameraControl.enableTorch(cameraInfo.torchState.value == TorchState.OFF)
                }
            } else {
                flashButton.visibility = View.GONE
            }

            cameraInfo.torchState.observe(viewLifecycleOwner) { torchState ->
                if (torchState == TorchState.OFF) {
                    flashButton.setImageResource(R.drawable.ic_flash)
                } else {
                    flashButton.setImageResource(R.drawable.ic_flash_active)
                }
            }
        }
    }

You need execute this method after initialize camera object

kazhiu
  • 749
  • 9
  • 21
  • Brilliant answer. Thanks for taking advantage of observing the torch state. Could use a little more explanation though. Still a great answer. – Sakiboy Dec 03 '20 at 19:42
5

Use CameraControl as global variable and boolean for turn off and on.

 lateinit var cameraControl: CameraControl
 private var flashFlag: Boolean = true

Turn off and on by click listener.

flashFlag = !flashFlag
cameraControl.enableTorch(flashFlag)

In this function I have started the camera preview.

private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

        cameraProviderFuture.addListener({
            // Used to bind the lifecycle of cameras to the lifecycle owner
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

            // Preview
            val preview = Preview.Builder()
                .build()
                .also {
                    it.setSurfaceProvider(binding.cameraView.surfaceProvider)
                }

            // Select back camera as a default
            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

            try {
                // Unbind use cases before rebinding
                cameraProvider.unbindAll()

                // Bind use cases to camera
                val camera = cameraProvider.bindToLifecycle(
                    this, cameraSelector, preview
                )
                cameraControl = camera.cameraControl
                cameraControl.enableTorch(flashFlag)

            } catch (exc: Exception) {
                Log.e(TAG, "Use case binding failed", exc)
            }

        }, ContextCompat.getMainExecutor(this))
    }
ahmad bajwa
  • 966
  • 2
  • 10
  • 30
3
val previewConfig = PreviewConfig.Builder().apply {
            setLensFacing(lensFacing)
            // Any setup
            setTargetRotation(viewFinder.display.rotation)
}.build()

val preview = Preview(previewConfig)

preview.enableTorch(true)
yevhen_69
  • 560
  • 3
  • 9
  • Sorry but enableTorch does not seem to work on my Huawei P10 Lite using Android 8.0. Preview is working fine but it seems that it just does not care about enableTorch(true). ¯\_(ツ)_/¯ Any ideas? – Pluto1010 Jun 24 '19 at 04:40
  • `enableTorch` is no longer a method of the class `Preview`; see https://developer.android.com/reference/androidx/camera/core/Preview.html – Adam Burley Jun 18 '21 at 16:33
3
androidx.camera:camera-core:1.0.0-alpha06

CameraX new release provide these features. CameraInfo added with check Flash Available and Sensor Rotation APIs, refer this link

try {
    CameraInfo cameraInfo = CameraX.getCameraInfo(currentCameraLensFacing);
    LiveData<Boolean> isFlashAvailable = cameraInfo.isFlashAvailable();
    flashToggle.setVisibility(isFlashAvailable.getValue() ? View.VISIBLE : View.INVISIBLE);
} catch (CameraInfoUnavailableException e) {
    Log.w(TAG, "Cannot get flash available information", e);
    flashToggle.setVisibility(View.VISIBLE);
}
Akshay Raiyani
  • 1,243
  • 9
  • 21
  • Where is this class `CameraX` you are using? I think CameraX is a library not a class, I cannot find any static method `CameraX.getCameraInfo` like what you have called here. also, this code snippet will only check the flash state and set the visibility of a toggle based on the flash state, it won't actually set the flash state – Adam Burley Jun 18 '21 at 16:31
  • This is the example when cameraX is in alpha, in latest version may be this class removed. – Akshay Raiyani Jun 19 '21 at 09:01
2

You can enable the torch on the Preview object. https://developer.android.com/reference/androidx/camera/core/Preview.html#enableTorch(boolean)

And you can set the flash mode (on/off/auto) on the ImageCapture object or on the config builder associated. https://developer.android.com/reference/androidx/camera/core/ImageCapture.html#setFlashMode(androidx.camera.core.FlashMode) https://developer.android.com/reference/androidx/camera/core/ImageCaptureConfig.Builder.html#setFlashMode(androidx.camera.core.FlashMode)

Rémi Latapy
  • 131
  • 1
  • 6