I'm an android developer beginner and i try to use CameraX.
Is it possible to open the native camera and take a picture instead of build a page with preview and custom button to take a photo ?
I've read multiple article / tutorial but cannot find the solution.
Thanks for helping me
Using the example here, with a few tweaks - I was able to take a photo without any preview.
First we start the camera using ImageCapture use case:
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
imageCapture = ImageCapture.Builder()
.build()
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, cameraSelector, imageCapture)
} catch(exc: Exception) {
Log.e("Error", "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
Then we can take a photo by calling takePhoto method:
private fun takePhoto() {
// Get a stable reference of the modifiable image capture use case
val imageCapture = imageCapture ?: return
// Create time stamped name and MediaStore entry.
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "sample_image")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
}
}
// Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions
.Builder(contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues)
.build()
// Set up image capture listener, which is triggered after photo has
// been taken
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Log.e("Error", "Photo capture failed: ${exc.message}", exc)
}
override fun
onImageSaved(output: ImageCapture.OutputFileResults){
val msg = "Photo capture succeeded: ${output.savedUri}"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d("Success", msg)
}
}
)
}
I've uploaded a working project to Github
Related
everyone. I have an app in which I want to take a photo. I followed Google's guide (https://developer.android.com/codelabs/camerax-getting-started#1). However, I cannot take a photo. I can't get to the error function nor the success function within takePicture(). I use SDK 30.
private fun takePhoto() {
// Get a stable reference of the modifiable image capture use case
//Here the return is called
val imageCapture = imageCapture ?: return
// Create time stamped name and MediaStore entry.
val name = SimpleDateFormat(FILENAME_FORMAT, Locale.GERMAN)
.format(System.currentTimeMillis())
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
}
}
// Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions
.Builder(contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues)
.build()
// Set up image capture listener, which is triggered after photo has
// been taken
imageCapture.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback {
//Will never be called
override fun onError(exc: ImageCaptureException) {
Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
}
//Will never be called
override fun
onImageSaved(output: ImageCapture.OutputFileResults){
val msg = "Photo capture succeeded: ${output.savedUri}"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG, msg)
}
}
)}
I am trying to record video with latest version of cameraX 1.0.0-beta11 but I am facing issue in recording it.
Code snippet to start camera and record video.
#SuppressLint("RestrictedApi")
private fun startCameraX() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(activity!!)
cameraProviderFuture.addListener(Runnable {
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
val videoCapture=VideoCapture.Builder().setVideoFrameRate(15).build()
val videoFile = File(
getOutputDirectory(),
SimpleDateFormat(FILENAME_FORMAT, Locale.US
).format(System.currentTimeMillis()) + ".mp4")
val outputOptions = VideoCapture.OutputFileOptions.Builder(videoFile).build()
videoCapture.startRecording(outputOptions, ContextCompat.getMainExecutor(activity), object: VideoCapture.OnVideoSavedCallback{
override fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {
Log.e("data","onVideoSaved")
}
override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
Log.e("data", "onError->$message")
}
})
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
cameraProvider.bindToLifecycle(
(this as LifecycleOwner), cameraSelector, preview, videoCapture)
} catch(exc: Exception) {
Log.e("TAG", "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(activity))
}
Output directory
private fun getOutputDirectory(): File {
val mediaDir = activity?.externalMediaDirs?.firstOrNull()?.let {
File(it, resources.getString(R.string.app_name)).apply { mkdirs() } }
return if (mediaDir != null && mediaDir.exists())
mediaDir else activity!!.filesDir
}
Error - Not bound to a Camera [androidx.camera.core.VideoCapture#4bd02a4]
Please help!!
Thanks in advance.
You must start the camera before calling the startRecording function. Basically you should output the following code in a function.
val videoFile = File(
getOutputDirectory(),
SimpleDateFormat(FILENAME_FORMAT, Locale.US
).format(System.currentTimeMillis()) + ".mp4")
val outputOptions = VideoCapture.OutputFileOptions.Builder(videoFile).build()
videoCapture.startRecording(outputOptions, ContextCompat.getMainExecutor(activity), object: VideoCapture.OnVideoSavedCallback{
override fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {
Log.e("data","onVideoSaved")
}
override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
Log.e("data", "onError->$message")
}
})
And call it when the user clicks record button, then, when user clicks stop button you can stop recording with
videoCapture.stopRecording()
Once stopRecording function is called, if everything is ok, onVideoSaved function is gonna be called
I'm trying to explore cameraX beta version.
I'm stuck in my implementation.
imageCapture.takePicture() imageCapture is null.
// Bind the CameraProvider to the LifeCycleOwner
val cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
// CameraProvider
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// ImageCapture
imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()
// Must unbind the use-cases before rebinding them
cameraProvider.unbindAll()
try {
// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, imageCapture)
} catch(exc: Exception) {
Log.e("TAG", "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
// Create output file to hold the image
photoFile = createFile(externalMediaDirs.first(), FILENAME, PHOTO_EXTENSION)
// Setup image capture metadata
val metadata = Metadata().apply {
// Mirror image when using the front camera
isReversedHorizontal = lensFacing == CameraSelector.LENS_FACING_FRONT
}
// Create output options object which contains file + metadata
outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile)
.setMetadata(metadata)
.build()
// Setup image capture listener which is triggered after photo has been taken
imageCapture?.takePicture(
outputOptions, cameraExecutor, object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val savedUri = output.savedUri ?: Uri.fromFile(photoFile)
Log.d(TAG, "Photo capture succeeded: $savedUri")
}
})
}
(I don't use onClickListener)
My function is called by a service.
If I remove cameraProviderFuture.addListener(Runnable I get Not bound to a valid Camera
I use camerax beta version
The ImageCapture use case doesn't currently work on its own. It has to be used in combination with at least a Preview or ImageAnalysis use case. This might change in future versions of CameraX. For now, you can check the documentation on supported use case combinations.
A simple fix to your problem would be to add an ImageAnalysis use case, its Analyzer can just immediately close the images it receives.
val imageAnalysis = ImageAnalysis.Builder()
.build()
.apply {
setAnalyzer(executor, ImageAnalysis.Analyzer { image ->
image.close()
})
}
// Then bind both the imageAnalysis and ImageCapture
cameraProvider.bindToLifecycle(this, cameraSelector, imageCapture, imageAnalysis)
Sorry about my English, I dont speak very well.
I have an app that comumnicates with an arduino device by blinking flash.
I notice that both Camera1 and Camera2 have issues to work into all Android devices, so I builded a settings screen that user can test both and choose the one that works fine.
I'm now trying to build the same communication with CameraX, hoping that works fine into more devices, but I cant find examples to just toggle the flash. I'm new at android develop, and the material I found is just about taking pictures and stuff, but I dont want even open a camera screen, just turn on and off the flash, like lantern.
Can someone help with this, or send a documentation that helps?
edit1
I did this in onCreate and I see the logs into logcat but flash dont toggle.
Maybe I need to create case ?
lateinit var cameraControl: CameraControl
val cameraProcessFuture = ProcessCameraProvider.getInstance(this)
cameraProcessFuture.addListener(Runnable {
val cameraProvider = cameraProcessFuture.get()
val lifecycleOwner = this
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector)
cameraControl = camera.cameraControl
val listenableFuture = cameraControl!!.enableTorch(true)
// cameraControl.enableTorch(false)
Log.d("MurilloTesteCamera", "listener")
listenableFuture.addListener(Runnable {
Log.d("MurilloTesteCamera", "listener 2")
}, ContextCompat.getMainExecutor(this))
}, ContextCompat.getMainExecutor(this))
Log.d("MurilloTesteCamera", "oncreate")
edit2
this code I tried to create a case, but no solve my problem and flash stil dont turn on ( my activity implements CameraXConfig.Provider:
val context = this
Log.d("MurilloTesteCamera", "before initialize")
CameraX.initialize(context, cameraXConfig).addListener(Runnable {
Log.d("MurilloTesteCamera", "inside initialize")
CameraX.unbindAll()
val preview = Preview.Builder()
.apply {
setTargetResolution(Size(640, 480))
}
.build()
lateinit var cameraControl: CameraControl
val cameraProcessFuture = ProcessCameraProvider.getInstance(context)
cameraProcessFuture.addListener(Runnable {
val cameraProvider = cameraProcessFuture.get()
val lifecycleOwner = context
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector)
cameraControl = camera.cameraControl
camera.cameraInfo.hasFlashUnit()
Log.d("MurilloTesteCamera", "info before -> " + camera.cameraInfo.torchState)
Log.d("MurilloTesteCamera", "has flash -> " + camera.cameraInfo.hasFlashUnit())
val listenableFuture = cameraControl.enableTorch(true)
Log.d("MurilloTesteCamera", "listener")
listenableFuture.addListener(Runnable {
Log.d("MurilloTesteCamera", "info after -> " + camera.cameraInfo.torchState)
Log.d("MurilloTesteCamera", "listener 2")
}, ContextCompat.getMainExecutor(context))
CameraX.bindToLifecycle(context, cameraSelector, preview)
}, ContextCompat.getMainExecutor(context))
}, ContextCompat.getMainExecutor(context))
Log.d("MurilloTesteCamera", "after initialize")
while (!CameraX.isInitialized()){}
Log.d("MurilloTesteCamera", "after while")
In CameraX, the API to turn on/off the camera torch is CameraControl.enableTorch(boolean). To get a CameraControl instance, you can follow the documentation:
The application can retrieve the CameraControl instance via
Camera.getCameraControl(). CameraControl is ready to start operations
immediately after Camera is retrieved and UseCases are bound to that
camera
This means you'll need to first bind a use case (or multiple use cases) to a lifecycle. You mentioned you don't want to open a camera screen, so I'm assuming you mean you don't want to bind any use cases, in which case you can call bindToLifecycle() with zero use cases. This may or may not work with the latest versions of CameraX.
All in all, you'd have to write something like this:
val cameraProcessFuture = ProcessCameraProvider.getInstance(context)
cameraProcessFuture.addListener(Runnable {
val cameraProvider = cameraProcessFuture.get()
// Choose the lifecycle to which the camera will be attached to
val lifecycleOwner = /* Can be an Activity, Fragment, or a custom lifecycleOwner */
// Choose a valid camera the device has
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// You might need to create a use case to start capture requests
// with the camera
val imageAnalysis = ImageAnalysis.Builder()
.build()
.apply {
val executor = /* Define an executor */
setAnalyzer(executor, ImageAnalysis.Analyzer {
it.close()
})
}
// Get a camera instance
val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector)
// Get a cameraControl instance
val cameraControl = camera.cameraControl
// Call enableTorch(), you can listen to the result to check whether it was successful
cameraControl.enableTorch(true) // enable torch
cameraControl.enableTorch(false) // disbale torch
}, ContextCompat.getMainExecutor(context))
I'm working with Camera X for the first time and I can't find a way to check if a device has a front or rear camera in runtime...
I only need to use the preview I'm not capturing images so i can't use a button for it..
private var lensFacing = CameraX.LensFacing.FRONT
val viewFinderConfig = PreviewConfig.Builder().apply {
setLensFacing(lensFacing)
setTargetAspectRatio(screenAspectRatio)
setTargetRotation(viewFinder.display.rotation)
}.build()
How can I make sure that the app won't crash if the user device has no Front camera?
Thanks in advance!
Check if the device supports at least one camera with the specified lens facing:
version 1.0.0-alpha06:
val hasFrontCamera = CameraX.hasCameraWithLensFacing(CameraX.LensFacing.FRONT)
EDIT :
version >= 1.0.0-alpha07:
From https://developer.android.com/jetpack/androidx/releases/camera:
hasCamera() previously provided by the CameraX class call are now
available via the ProcessCameraProvider
override fun onCreate(savedInstanceState: Bundle?) {
cameraProviderFuture = ProcessCameraProvider.getInstance(this);
}
cameraProviderFuture.addListener(Runnable {
val cameraProvider = cameraProviderFuture.get()
try {
var hasCamera = cameraProvider.hasCamera(CameraSelector.DEFAULT_FRONT_CAMERA)
} catch (e: CameraInfoUnavailableException) {
e.printStackTrace()
}
}, ContextCompat.getMainExecutor(this))