CameraX has released the 1.0 official version of the App involving the use of the camera, can make full use of the camera has a big difference, so it is necessary to understand and recognize the CameraX.
📑 Soon to learn
Create camera, shoot, and preview with the Jetpack component support library CameraX
â• requirements
CameraX is a Jetpack component support library that will help simplify the development of camera-related applications. It also provides a consistent and easy-to-use API for most Android devices, with backward compatibility to Android 5.0 (API level 21)
Therefore, when creating an Android application, mininumSDK needs to select 5.0
Prepend content
Take a photo with Intent
The easiest way to take a photo in your application is to use mediastore.action_image_capture, pass in the Intent and launch it
This will activate the system camera and provide the user with a full set of camera capabilities and at this point, if the user grants the user permission to take a photo, and they’re satisfied with the photo, we’ll be able toonActivityResult
By default, the photo taken is returned as a thumbnail, which can be obtained using the data key
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
Copy the code
To get the full image, in the Intent that launched the camera, add the mediastore. EXTRA_OUTPUT parameter to the Intent and set the output URI of the file. The URI will store the full photo
After the storage of the complete picture path after the picture and SettingsThis storage setting has some limitations. For details, see the official operation on taking photos Photos | | Android Developers Android Developers (Google, cn)) These are some of the operations that we use in our daily life to get images from the camera. During development, we still had a lot of dirty code when using the API for Camera2, and CameraX came out as a Jetpack component from Google. To simplify Camera development, let’s see how to use CameraX
In actual combat
Create a project
Add and synchronize the CameraX dependency in the App module
Use PreviewView to implement the CameraX preview
1. Add a PreviewView to the layout file
Make changes in the layout file
Manifest states camera permissions
<uses-permission android:name="android.permission.CAMERA" />
Copy the code
Dynamically apply for camera permissions
/ / overwrite onRequestPermissionsResult () method
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
Toast.makeText(this."Permission not granted by user",
Toast.LENGTH_SHORT).show()
finish()
}
}
Copy the code
2. Request ProcessCameraProvider
ProcessCameraProvider is a singleton that binds the camera’s lifecycle to any lifecycle holder in the application process. Because The cameraX has life cycle sensing, this saves our application the task of turning the camera on and off
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
Copy the code
Check the availability of ProcessCameraProvider
cameraProviderFuture.addListener(Runnable {}, ContextCompat.getMainExecutor(this))
Copy the code
4. When ProcessCameraProvider is available, select the camera and bind the life cycle and use case
- Create a Preview
- Specify the camera you want
- Bind the selected camera and any use case to the life cycle
- will
Preview
Connect to thePreviewView
cameraProviderFuture.addListener(Runnable {
// 1 Bind the Camera to the lifecycle holder
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get(a)// 2 Create Preview.
val preview = Preview.Builder()
.build()
.also {
/ / the preview link previewView
it.setSurfaceProvider(findViewById<PreviewView>(R.id.viewFinder).getSurfaceProvider())
}
//3 Specifies the camera required
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// 4 Unbind before binding
cameraProvider.unbindAll()
// 5 Bind the user case and camera to the life cycle
cameraProvider.bindToLifecycle(
this, cameraSelector, preview)
} catch(exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
Copy the code
rendering
This is a preview of the camera
CameraX photos
Configure the app to take pictures
- Use ImageCapture.Builder to build ImageCapture
- Bind the user case and camera to the life cycle by adding an imageCapture
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
Copy the code
Taking pictures
- Gets a reference to the ImageCapture use case
- Create image store to hold file
- create
OutputFileOptions
Specify the output mode and output path
valoutputFileOptions = ImageCapture.OutputFileOptions.Builder(File(...) ).build()Copy the code
- right
imageCapture
The objecttakePicture()
Methods. Pass in what you just builtoutputOptions
And a callback to save the image
Final modification code
cameraProviderFuture.addListener(Runnable {
// 1 Bind the Camera to the lifecycle holder
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get(a)// 2 Create Preview.
val preview = Preview.Builder()
.build()
.also {
/ / the preview link previewView
it.setSurfaceProvider(findViewById<PreviewView>(R.id.viewFinder).getSurfaceProvider())
}
/ / todo new lines
// Image capture build
imageCapture = ImageCapture.Builder()
.build()
//3 Specifies the camera required
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// 4 Unbind before binding
cameraProvider.unbindAll()
// Todo adds a modified row
// 5 Bind the user case and camera to the life cycle
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture)
} catch(exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
Copy the code
private fun takePhoto(a) {
// Get the image capture use case
valimageCapture = imageCapture ? :return
// Create a storage file object
val photoFile = File(
outputDirectory,
SimpleDateFormat(FILENAME_FORMAT, Locale.CHINA
).format(System.currentTimeMillis()) + ".jpg")
// Output conditional builds
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
// Take an incoming output condition and take a callback
imageCapture.takePicture(
outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
// Print the exception
Log.e(TAG, "Failed to take a photo:${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val savedUri = Uri.fromFile(photoFile)
val msg = "Photo taken successfully:$savedUri"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG, msg)
}
})
}
Copy the code
Run the show