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