I have a problem very similar to this.
I’m encountering a crash in my app when using CameraX with Compose Navigation. The issue occurs inconsistently: sometimes it crashes when opening the bottom navigation camera tab, and other times it crashes when navigating away. Other times it takes 2 or 3 times to navigate until it crashes. The problem occurs on Android 11, but it’s working fine on Android 12.
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
var isBottomNavigationVisible by remember { mutableStateOf(false) }
navController.addOnDestinationChangedListener { _, destination, _ ->
isBottomNavigationVisible = destination.route?.startsWith(Destination.HomeScreen.route) == true
}
Scaffold(
bottomBar = {
if (isBottomNavigationVisible) {
BottomNavigationBar(navController = navController)
}
}
) { innerPadding ->
LotusNavGraph(navController, innerPadding)
}
}
}
}
@Composable
fun BottomNavigationBar(navController: NavHostController) {
...
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
NavigationBar {
items.forEach { item ->
val isSelected = currentDestination?.hierarchy?.any { it.route == item.route } == true
NavigationBarItem(selected = isSelected, onClick = {
navController.navigate(item.route)
}
...
)
}
}
}
@Composable
fun LotusNavGraph(navController: NavHostController, innerPadding: PaddingValues) {
NavHost(
navController = navController,
startDestination = Destination.HomeScreen.route,
modifier = Modifier.padding(innerPadding)
) {
navigation(
startDestination = Destination.BottomNavigation.TicketsSection.route,
route = Destination.HomeScreen.route
) {
...
composable(Destination.BottomNavigation.ControlSection.route) {
ControlRoute()
}
}
}
}
@Composable
fun ControlRoute() {
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val cameraProviderFuture = remember { ProcessCameraProvider.getInstance(context) }
val cameraProvider = remember { cameraProviderFuture.get() }
val executor = remember(context) { ContextCompat.getMainExecutor(context) }
var imageCapture: ImageCapture? by remember { mutableStateOf(null) }
var preview by remember { mutableStateOf<Preview?>(null) }
var lensFacing by remember { mutableIntStateOf(CameraSelector.LENS_FACING_BACK) }
Box(Modifier.fillMaxSize()) {
AndroidView(
factory = { ctx ->
val previewView = PreviewView(ctx)
cameraProviderFuture.addListener({
val cameraSelector = CameraSelector.Builder()
.requireLensFacing(lensFacing)
.build()
imageCapture = ImageCapture.Builder()
.setTargetRotation(previewView.display.rotation)
.build()
preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
lifecycleOwner, cameraSelector, imageCapture, preview
)
}, executor)
previewView
},
modifier = Modifier.fillMaxSize()
)
}
}
I removed the permissions logic since I’m positive it’s not the reason for the crash.
Logs information
Camera:
{Camera@46f57cd[id=0]} Transitioning camera internal state: CLOSING --> INITIALIZED
Recalculating open cameras:
Camera State
-------------------------------------------------------------------
Camera@46f57cd[id=0] CLOSED
Camera@3d12ace[id=1] UNKNOWN
-------------------------------------------------------------------
Open count: 0 (Max allowed: 1)
New public camera state CameraState{type=CLOSED, error=null} from CLOSED and null
Publishing new public camera state CameraState{type=CLOSED, error=null}
ImageReader_JNI Unable to acquire a buffer item, very likely client tried to acquire more than maxImages buffers
Surface Lifecycle:
Surface destroyed.
Surface closed androidx.camera.core.SurfaceRequest@316af04
surface closed, useCount=1 closed=true androidx.camera.core.SurfaceRequest$2@b13eced
surface closed, useCount=0 closed=true androidx.camera.core.processing.SurfaceEdge$SettableSurface@1ed96b1
Surface terminated[total_surfaces=2, used_surfaces=1](androidx.camera.core.processing.SurfaceEdge$SettableSurface@1ed96b1}
use count-1, useCount=0 closed=true androidx.camera.core.SurfaceRequest$2@b13eced
Surface no longer in use[total_surfaces=2, used_surfaces=0](androidx.camera.core.SurfaceRequest$2@b13eced}
Surface terminated[total_surfaces=1, used_surfaces=0](androidx.camera.core.SurfaceRequest$2@b13eced}
Safe to release surface.
{Camera@46f57cd[id=0]} Use case androidx.camera.core.ImageCapture-be36803c-93ad-4eea-a1d0-8d855f812b99106716812 ACTIVE
Active and attached use case: [] for camera: 0
Surface created[total_surfaces=3, used_surfaces=0](androidx.camera.core.SurfaceRequest$2@8f91d90}
New surface in use[total_surfaces=3, used_surfaces=1](androidx.camera.core.SurfaceRequest$2@8f91d90}
Right before app stop:
runtime.cc:655] Runtime aborting...
runtime.cc:655] Dumping all threads without mutator lock held
runtime.cc:655] All threads:
runtime.cc:655] DALVIK THREADS (22):
runtime.cc:655] "hwuiTask1" prio=6 tid=25 Runnable
...
Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 3795