preface
This article is just a simple introduction to CameraX, which includes camera preview, photography, and simple image profiling.
Refer to the official document: developer. The android. Google. Cn/training/ca…
This article Demo code: github.com/L-X-J/Jetpa…
Overview (from official document)
While it leverages the capabilities of camera2, it uses a simpler, use-case-based approach with lifecycle awareness. It also addresses device compatibility issues, so you don’t need to include device-specific code in your code base. These features reduce the amount of code you need to write to add camera functionality to your application.
Finally, with CameraX, developers can take advantage of the same camera experience and functionality as a pre-installed camera app with just two lines of code. The CameraX Extensions is an optional plug-in that allows you to add portrait, HDR, Night mode, and beauty effects to your application on supported devices.
Introduction of depend on
implementation 'androidx. Camera, camera - core: 1.0.0 - alpha06'
implementation 'androidx. Camera, camera - camera2:1.0.0 - alpha06'
Copy the code
Implement camera preview
Drawing layout
Add a TextureView to the XML layout file and take an ID
<TextureView
android:id="@+id/view_finder"
.
android:layout_width="380dp"
android:layout_height="380dp"/>
Copy the code
Logical code implementation
Add two new methods to the activity.
private fun startCamera(a){}
private fun updateTransform(a){}
Copy the code
Because we need to realize the CAMERA preview dynamic access permissions (Manifest) permission) CAMERA). After obtaining permission, we need to call the startCamera() function. The following code
class MainActivity : AppCompatActivity() ,LifecycleOwner {
private lateinit var viewFinder : TextureView
private val executor = Executors.newSingleThreadExecutor()
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewFinder = findViewById(R.id.view_finder)
// Custom functions check whether permissions are owned
if (checkAllPermissionsGranted()){
viewFinder.post { startCamera() }
}else{
// If you do not have permission to dynamically obtain
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
viewFinder.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
updateTransform()
}
}
}
Copy the code
Finally, we implement the startCamera() and updateTransform() functions.
private fun startCamera(a){
// Create configuration objects for the viewfinder use case
val previewConfig = PreviewConfig.Builder().apply {
setTargetResolution(Size(viewFinder.width,viewFinder.height))
}.build()
// Build the viewfinder use case
val preview = Preview(previewConfig);
// Recalculate the layout every time the viewfinder is updated
preview.setOnPreviewOutputUpdateListener {
To update the SurfaceTexture, we must remove it and re-add it
val parent = viewFinder.parent as ViewGroup
parent.removeView(viewFinder)
parent.addView(viewFinder, 0)
viewFinder.surfaceTexture = it.surfaceTexture
updateTransform()
}
// Bind the use case to the lifecycle
CameraX.bindToLifecycle(this, preview)
}
private fun updateTransform(a) {
val matrix = Matrix()
// Calculate the center of the viewfinder
val centerX = viewFinder.width / 2f
val centerY = viewFinder.height / 2f
// Correct preview output to accommodate display rotation
val rotationDegrees = when(viewFinder.display.rotation) {
Surface.ROTATION_0 -> 0
Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270
else -> return
}
matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)
// Finally, apply the transformation to our TextureView
viewFinder.setTransform(matrix)
}
Copy the code
So now we have camera preview, which is a lot easier than before.
Taking pictures
To do this, we need to modify the startCamera() function, again with very little code.
private fun startCamera(a){...// Add the following code before camerax. bindToLifecycle(this, preview)
// Create a configuration object for the image capture use case
val imageCaptureConfig = ImageCaptureConfig.Builder().apply {
// We did not set the resolution for the image capture; Instead, we
// Select a capture mode that can be inferred to be appropriate
// Resolution based on aspect ratio and request mode
setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
}.build()
// Build an image capture use case and attach a button click listener
val imageCapture = ImageCapture(imageCaptureConfig)
// Take a photo button
findViewById<ImageButton>(R.id.capture_button).setOnClickListener {
val file = File(externalMediaDirs.first(),"${System.currentTimeMillis()}.jpg")
imageCapture.takePicture(file,executor,object : ImageCapture.OnImageSavedListener{
override fun onImageSaved(file: File) {
val msg = "Success:${file.absolutePath}"
Log.d("CameraXApp", msg)
viewFinder.post {
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
}
}
override fun onError(
imageCaptureError: ImageCapture.ImageCaptureError,
message: String,
cause: Throwable?). {
val msg = "The failure:$message"
Log.e("CameraXApp", MSG, cause) viewfinder.post {toast.maketext (baseContext, MSG, toast.length_short).show()}})Camerax. bindToLifecycle(this, preview)// Just preview
CameraX.bindToLifecycle(this, preview,imageCapture)// It can be previewed and photographed
}
Copy the code