Today we will discuss how to build a flashlight in Jetpack Compose.
Step-by-step Guide
- Setting up dependency
- Setting up Manifest
- Code Explanation
- Code Implementation
Setting up dependencies
We will be utilising Google's new API for permission requests in our app as it provides a more elegant way of requesting permission in our apps. Since it is a work in progress, there are some known limitations like not being able to check if the user is requesting the app for the first time etc. For more info, check this out
Now, in your build.gradle.kts
or build.gradle
file add the dependency
// Dependency to request hardware permission
implementation ("com.google.accompanist:accompanist-permissions:0.32.0")
Setting up Manifest
In your AndroidManifest.xml
file, add the code below inside your application tag
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
Code Explanation
fun toggleFlashLight(cameraManager: CameraManager, cameraId: String, isFlashOn: Boolean) {
try {
cameraManager.setTorchMode(cameraId, isFlashOn)
} catch (e: Exception) {
e.printStackTrace()
}
}
fun handlePermissionDenied(context: Context) {
Toast.makeText(context, "Please grant camera permission", Toast.LENGTH_LONG).show()
}
fun handlePermissionRationale(context: Context) {
Toast.makeText(context, "Camera permission is needed", Toast.LENGTH_LONG).show()
}
@OptIn(ExperimentalPermissionsApi::class)
fun handleLogic(
cameraPermissionState: PermissionState,
context: Context,
cameraManager: CameraManager,
cameraId: String,
isFlashOn: Boolean,
updateState: (Boolean) -> Unit,
) {
if (cameraPermissionState.status.isGranted) {
val newState = !isFlashOn
updateState(newState)
toggleFlashLight(cameraManager, cameraId, newState)
} else if (cameraPermissionState.status.shouldShowRationale) {
handlePermissionRationale(context)
cameraPermissionState.launchPermissionRequest()
} else {
handlePermissionDenied(context)
cameraPermissionState.launchPermissionRequest()
}
}
Code Implementation
import android.Manifest
import android.content.Context
import android.hardware.camera2.CameraManager
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.kotlin_articles.ui.theme.KotlinarticlesTheme
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import com.google.accompanist.permissions.shouldShowRationale
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
KotlinarticlesTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun Greeting(modifier: Modifier = Modifier) {
val context: Context = LocalContext.current
val cameraPermissionState = rememberPermissionState(permission = Manifest.permission.CAMERA)
var isFlashOn: Boolean by rememberSaveable {
mutableStateOf(false)
}
val cameraManager: CameraManager = remember {
context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
}
val cameraId: String = rememberSaveable {
try {
cameraManager.cameraIdList[0]
} catch (e: Exception) {
"0"
}
}
Column(
modifier = Modifier
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Button(
modifier = Modifier.height(50.dp),
onClick = {
handleLogic(
cameraPermissionState,
context,
cameraManager,
cameraId,
isFlashOn
) { isFlashOn = it }
},
) {
Text(
text = "Turn flashlight ${if (isFlashOn) "Off" else "On"} !",
fontSize = 16.sp,
textAlign = TextAlign.Center
)
}
}
}
fun toggleFlashLight(cameraManager: CameraManager, cameraId: String, isFlashOn: Boolean) {
try {
cameraManager.setTorchMode(cameraId, isFlashOn)
} catch (e: Exception) {
e.printStackTrace()
}
}
fun handlePermissionDenied(context: Context) {
Toast.makeText(context, "Please grant camera permission", Toast.LENGTH_LONG).show()
}
fun handlePermissionRationale(context: Context) {
Toast.makeText(context, "Camera permission is needed", Toast.LENGTH_LONG).show()
}
@OptIn(ExperimentalPermissionsApi::class)
fun handleLogic(
cameraPermissionState: PermissionState,
context: Context,
cameraManager: CameraManager,
cameraId: String,
isFlashOn: Boolean,
updateState: (Boolean) -> Unit,
) {
if (cameraPermissionState.status.isGranted) {
val newState = !isFlashOn
updateState(newState)
toggleFlashLight(cameraManager, cameraId, newState)
} else if (cameraPermissionState.status.shouldShowRationale) {
handlePermissionRationale(context)
cameraPermissionState.launchPermissionRequest()
} else {
handlePermissionDenied(context)
cameraPermissionState.launchPermissionRequest()
}
}
Happy coding!!!
You can check out the repo
Top comments (0)