Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Just toggle flash with CameraX

Sorry about my English, I dont speak very well.

I have an app that comumnicates with an arduino device by blinking flash. I notice that both Camera1 and Camera2 have issues to work into all Android devices, so I builded a settings screen that user can test both and choose the one that works fine.

I'm now trying to build the same communication with CameraX, hoping that works fine into more devices, but I cant find examples to just toggle the flash. I'm new at android develop, and the material I found is just about taking pictures and stuff, but I dont want even open a camera screen, just turn on and off the flash, like lantern.

Can someone help with this, or send a documentation that helps?

edit1

I did this in onCreate and I see the logs into logcat but flash dont toggle. Maybe I need to create case ?

lateinit var cameraControl: CameraControl
val cameraProcessFuture = ProcessCameraProvider.getInstance(this)
cameraProcessFuture.addListener(Runnable {
    val cameraProvider = cameraProcessFuture.get()

    val lifecycleOwner = this

    val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

    val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector)

    cameraControl = camera.cameraControl


    val listenableFuture = cameraControl!!.enableTorch(true)

    // cameraControl.enableTorch(false)
    Log.d("MurilloTesteCamera", "listener")
    listenableFuture.addListener(Runnable {

        Log.d("MurilloTesteCamera", "listener 2")
    }, ContextCompat.getMainExecutor(this))

}, ContextCompat.getMainExecutor(this))
Log.d("MurilloTesteCamera", "oncreate")

edit2

this code I tried to create a case, but no solve my problem and flash stil dont turn on ( my activity implements CameraXConfig.Provider:

val context = this

Log.d("MurilloTesteCamera", "before initialize")
CameraX.initialize(context, cameraXConfig).addListener(Runnable {

    Log.d("MurilloTesteCamera", "inside initialize")


    CameraX.unbindAll()

    val preview = Preview.Builder()
        .apply {
            setTargetResolution(Size(640, 480))
        }
        .build()


    lateinit var cameraControl: CameraControl

    val cameraProcessFuture = ProcessCameraProvider.getInstance(context)
    cameraProcessFuture.addListener(Runnable {
        val cameraProvider = cameraProcessFuture.get()

        val lifecycleOwner = context

        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

        val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector)

        cameraControl = camera.cameraControl

        camera.cameraInfo.hasFlashUnit()

        Log.d("MurilloTesteCamera", "info before -> " + camera.cameraInfo.torchState)
        Log.d("MurilloTesteCamera", "has flash -> " + camera.cameraInfo.hasFlashUnit())



        val listenableFuture = cameraControl.enableTorch(true)

        Log.d("MurilloTesteCamera", "listener")
        listenableFuture.addListener(Runnable {
            Log.d("MurilloTesteCamera", "info after -> " + camera.cameraInfo.torchState)

            Log.d("MurilloTesteCamera", "listener 2")
        }, ContextCompat.getMainExecutor(context))

        CameraX.bindToLifecycle(context, cameraSelector, preview)

    }, ContextCompat.getMainExecutor(context))



}, ContextCompat.getMainExecutor(context))

Log.d("MurilloTesteCamera", "after initialize")
while (!CameraX.isInitialized()){}
Log.d("MurilloTesteCamera", "after while")
like image 488
Murillo Minuscoli Maciel Avatar asked May 13 '20 14:05

Murillo Minuscoli Maciel


1 Answers

In CameraX, the API to turn on/off the camera torch is CameraControl.enableTorch(boolean). To get a CameraControl instance, you can follow the documentation:

The application can retrieve the CameraControl instance via Camera.getCameraControl(). CameraControl is ready to start operations immediately after Camera is retrieved and UseCases are bound to that camera

This means you'll need to first bind a use case (or multiple use cases) to a lifecycle. You mentioned you don't want to open a camera screen, so I'm assuming you mean you don't want to bind any use cases, in which case you can call bindToLifecycle() with zero use cases. This may or may not work with the latest versions of CameraX.

All in all, you'd have to write something like this:

val cameraProcessFuture = ProcessCameraProvider.getInstance(context)
cameraProcessFuture.addListener(Runnable {
    val cameraProvider = cameraProcessFuture.get()

    // Choose the lifecycle to which the camera will be attached to
    val lifecycleOwner = /* Can be an Activity, Fragment, or a custom lifecycleOwner */

    // Choose a valid camera the device has
    val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

    // You might need to create a use case to start capture requests 
    // with the camera
    val imageAnalysis = ImageAnalysis.Builder()
          .build()
          .apply {
              val executor = /* Define an executor */
              setAnalyzer(executor, ImageAnalysis.Analyzer {
                  it.close()
              })
           }

    // Get a camera instance
    val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector)

    // Get a cameraControl instance
    val cameraControl = camera.cameraControl

    // Call enableTorch(), you can listen to the result to check whether it was successful
    cameraControl.enableTorch(true) // enable torch
    cameraControl.enableTorch(false) // disbale torch
}, ContextCompat.getMainExecutor(context))
like image 198
Husayn Hakeem Avatar answered Sep 29 '22 19:09

Husayn Hakeem