Reputation: 31
I am using CameraX use cases to display image from camera on the screen and at the same time perform object detection on it. You can find below the code related to CameraX, located in the onCreate() function of my main activity.
Nonetheless, I get an error on some (let's say 1/5) app initialization, without any code or binary modification between the working and non working cases:
java.lang.NullPointerException: previewView.display must not be null
And if I try not to access previewView.display to avoid the crash, I just get images with empty crop until I restart the app.
It seems that it is related to view initialization and useCaseGroup but I can't figure out why I get different results on successive app startup.
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_4_3)
.setTargetRotation(***previewView.display.rotation)
.build()
.also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
val imageAnalyzer = ImageAnalysis.Builder()
.setTargetAspectRatio(AspectRatio.RATIO_4_3)
.setTargetRotation(previewView.display.rotation)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
.also {
it.setAnalyzer(
cameraExecutor,
PreprocessingAnalyzer(
context,
extendedBitmapInputStream,
previewView
)
)
}
val aspectRatio = Rational(previewView.width, previewView.height)
val viewPort = ViewPort.Builder(aspectRatio, preview.targetRotation).build()
val useCaseGroup = UseCaseGroup.Builder()
.addUseCase(preview)
.addUseCase(imageAnalyzer)
.setViewPort(viewPort)
.build()
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
cameraProvider.bindToLifecycle(this, cameraSelector, useCaseGroup)
}, ContextCompat.getMainExecutor(this))
Upvotes: 1
Views: 1232
Reputation: 31
The snippet I provided was located in onCreate() when it should have been located in onResume().
In fact, even if Views are already initialized in onCreate(), they are not necessarily ready for being displayed because the activity is not really running until onResume() callback.
The randomness came from the fact that I only have 1 Activity, and so onCreate() and onResume() calls were really close in time.
This link provides useful information to better understand the activity lifecycle.
Upvotes: 1