Android CameraX: Difference between revisions
Jump to navigation
Jump to search
Line 45: | Line 45: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | |||
=Compose= | |||
I am loving the new compose. It takes a lot of the tedium out of it all. This did not exist last time. Basically bye, bye XML. Lot of code here but you just make the bits and add the components inline. The CameraPreview is the implementation of the previewer in Xml. This | |||
<syntaxhighlight lang="kotlin"> | |||
setContent { | |||
CameraXTutTheme { | |||
Scaffold { | |||
val scaffoldState = rememberBottomSheetScaffoldState() | |||
val controller = remember { | |||
LifecycleCameraController(applicationContext).apply { | |||
setEnabledUseCases( | |||
CameraController.IMAGE_CAPTURE or | |||
CameraController.VIDEO_CAPTURE | |||
) | |||
} | |||
} | |||
BottomSheetScaffold( | |||
scaffoldState = scaffoldState, | |||
sheetPeekHeight = 0.dp, | |||
sheetContent = { | |||
} | |||
) { padding -> | |||
Box( | |||
modifier = Modifier | |||
.fillMaxSize() | |||
.padding(padding) | |||
) { | |||
CameraPreview( | |||
controller, | |||
Modifier.fillMaxSize() | |||
) | |||
IconButton( | |||
onClick = { | |||
controller.cameraSelector = | |||
if (controller.cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) { | |||
CameraSelector.DEFAULT_FRONT_CAMERA | |||
} else { | |||
CameraSelector.DEFAULT_BACK_CAMERA | |||
} | |||
}, | |||
modifier = Modifier.padding(16.dp) | |||
) { | |||
Icon( | |||
imageVector = Icons.Default.Cameraswitch, | |||
contentDescription = "Switch Camera" | |||
) | |||
} | |||
Row( | |||
modifier = Modifier | |||
.fillMaxWidth() | |||
.align(Alignment.BottomCenter) | |||
.padding(16.dp), | |||
horizontalArrangement = Arrangement.SpaceAround | |||
) { | |||
IconButton( | |||
onClick = { | |||
} | |||
) { | |||
Icon( | |||
imageVector = Icons.Default.Photo, | |||
contentDescription = "Open Gallery" | |||
) | |||
} | |||
IconButton( | |||
onClick = { | |||
} | |||
) { | |||
Icon( | |||
imageVector = Icons.Default.PhotoCamera, | |||
contentDescription = "Take Photo" | |||
) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> |
Revision as of 04:20, 6 March 2025
Introduction
Already had this working for my Food app but this is now broken so watching a tutorial and thought I better take notes
Setup Permissions
Make sure we give permissions in the Manifest
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
Implement Permission Checking
This is the simplest way to get going
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (!hasRequiredPermissions()) {
requestPermissions(CAMERAX_PERMISSIONS, 0)
}
enableEdgeToEdge()
}
private fun hasRequiredPermissions(): Boolean {
return CAMERAX_PERMISSIONS.all {
ContextCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
}
}
companion object {
private val CAMERAX_PERMISSIONS = arrayOf(
android.Manifest.permission.CAMERA,
android.Manifest.permission.RECORD_AUDIO
)
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
}
Compose
I am loving the new compose. It takes a lot of the tedium out of it all. This did not exist last time. Basically bye, bye XML. Lot of code here but you just make the bits and add the components inline. The CameraPreview is the implementation of the previewer in Xml. This
setContent {
CameraXTutTheme {
Scaffold {
val scaffoldState = rememberBottomSheetScaffoldState()
val controller = remember {
LifecycleCameraController(applicationContext).apply {
setEnabledUseCases(
CameraController.IMAGE_CAPTURE or
CameraController.VIDEO_CAPTURE
)
}
}
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetPeekHeight = 0.dp,
sheetContent = {
}
) { padding ->
Box(
modifier = Modifier
.fillMaxSize()
.padding(padding)
) {
CameraPreview(
controller,
Modifier.fillMaxSize()
)
IconButton(
onClick = {
controller.cameraSelector =
if (controller.cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
CameraSelector.DEFAULT_FRONT_CAMERA
} else {
CameraSelector.DEFAULT_BACK_CAMERA
}
},
modifier = Modifier.padding(16.dp)
) {
Icon(
imageVector = Icons.Default.Cameraswitch,
contentDescription = "Switch Camera"
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.align(Alignment.BottomCenter)
.padding(16.dp),
horizontalArrangement = Arrangement.SpaceAround
) {
IconButton(
onClick = {
}
) {
Icon(
imageVector = Icons.Default.Photo,
contentDescription = "Open Gallery"
)
}
IconButton(
onClick = {
}
) {
Icon(
imageVector = Icons.Default.PhotoCamera,
contentDescription = "Take Photo"
)
}
}
}
}
}
}
}