CameraXでカメラのライト(トーチ)をON/OFFする方法。

Camera オブジェクトの取得

ライトの制御には Camera オブジェクトが必要である。cameraProvider.bindToLifecycle() の戻り値として取得できる。

var camera by remember { mutableStateOf<Camera?>(null) }

LaunchedEffect(lifecycleOwner) {
    // ... cameraProvider のセットアップ ...

    camera = cameraProvider.bindToLifecycle(
        lifecycleOwner,
        CameraSelector.DEFAULT_BACK_CAMERA,
        preview,
        imageAnalysis
    )
}

ライトのON/OFF

camera.cameraControl.enableTorch() でライトを制御する。
isTorchEnabled の状態が変化したとき、または camera が初期化されたときに呼ばれるよう LaunchedEffect のキーに両方を指定する。

LaunchedEffect(isTorchEnabled, camera) {
    camera?.cameraControl?.enableTorch(isTorchEnabled)
}

ボタンで切り替えるUI

FloatingActionButton でON/OFFを切り替える例。

var isTorchEnabled by remember { mutableStateOf(false) }

Scaffold(
    floatingActionButton = {
        FloatingActionButton(onClick = { isTorchEnabled = !isTorchEnabled }) {
            Text(if (isTorchEnabled) "OFF" else "ON")
        }
    }
) { innerPadding ->
    CameraPreview(
        isTorchEnabled = isTorchEnabled,
        // ...
    )
}

CameraPreview Composableでは isTorchEnabled を引数として受け取り、上記の LaunchedEffect で反映する。

アプリ切り替え時のUI同期

アプリをバックグラウンドに移動すると、CameraXはライフサイクルに連動してライトを自動的に消す。しかし isTorchEnabled の状態はそのまま維持されるため、フォアグラウンドへ戻ったとき、ライトはすでに消えているのにボタンが「OFF」と表示されたままになる。

LifecycleEventEffect を使って ON_STOP 時に isTorchEnabled をリセットすることで解決する。

LifecycleEventEffect(Lifecycle.Event.ON_STOP) {
    isTorchEnabled = false
}

LifecycleEventEffectlifecycle-runtime-compose に含まれる。

implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.0")