-
CameraX的介绍
-
CameraX的基础使用
-
CameraX的进阶使用
CameraX的介绍
=============
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
========================================================
CameraX 是一个 Jetpack 支持库,旨在帮助您简化相机应用的开发工作。它提供了一个一致且易于使用的API界面,可以兼容至android5.0。(API 级别 21)
CameraX的基础使用
=======================================================================
本文章使用kotlin代码
第一步
要使用CameraX首先要在build.gradle(module:app)的dependencies{}里添加如下代码:
def camerax_version = “1.0.0-beta07”
// 使用camera2实现的CameraX核心库
implementation “androidx.camera:camera-camera2:$camerax_version”
// CameraX生命周期库
implementation “androidx.camera:camera-lifecycle:$camerax_version”
// CameraX View类
implementation “androidx.camera:camera-view:1.0.0-alpha14”
然后进行gradle同步(这里可能需要开代理)
第二步
在主要布局文件里创建一个Button和一个androidx.camera.view.PreviewView(使用自定义的Button会更好)如下:
android:id="@+id/camera_capture_button" android:layout_width=“92dp” android:layout_height=“92dp” android:layout_marginBottom=“80dp” android:scaleType=“fitCenter” android:background="@drawable/ic_shutter" app:layout_constraintLeft_toLeftOf=“parent” app:layout_constraintRight_toRightOf=“parent” app:layout_constraintBottom_toBottomOf=“parent” android:elevation=“2dp” />
android:id="@+id/viewFinder" android:layout_width=“match_parent” android:layout_height=“match_parent” /> 第三步 在AndroidManifest.xml文件中申请权限 在第四步中要在activity的kt文件中添加请求权限的方法 第四步 创建mainactivity的kt文件,代码如下: import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.Manifest import android.content.pm.PackageManager import android.net.Uri import android.util.Log import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import java.util.concurrent.Executors import androidx.camera.core.* import androidx.camera.lifecycle.ProcessCameraProvider import kotlinx.android.synthetic.main.activity_main.* import java.io.File import java.nio.ByteBuffer import java.text.SimpleDateFormat import java.util.* import java.util.concurrent.ExecutorService typealias LumaListener = (luma: Double) -> Unit class MainActivity : AppCompatActivity() { private var imageCapture: ImageCapture? = null private lateinit var outputDirectory: File private lateinit var cameraExecutor: ExecutorService override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 请求相机权限 if (allPermissionsGranted()) { startCamera() } else { ActivityCompat.requestPermissions( this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS) } // 设置拍照的监听按钮 camera_capture_button.setonClickListener { takePhoto() } outputDirectory = getOutputDirectory() cameraExecutor = Executors.newSingleThreadExecutor() } private fun takePhoto() { // 获得可修改的图像捕获用例 val imageCapture = imageCapture ?: return // 创建带时间戳的输出文件用于保存文件 val photoFile = File( outputDirectory, SimpleDateFormat(FILENAME_FORMAT, Locale.US ).format(System.currentTimeMillis()) + “.jpg”) // 创建输出选项对象 val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build() // 设置图像捕获监听器,拍照后触发 imageCapture.takePicture( outputOptions, ContextCompat.getMainExecutor(this), 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 = Uri.fromFile(photoFile) val msg = “Photo capture succeeded: $savedUri” Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show() Log.d(TAG, msg) } }) } private fun startCamera() { val cameraProviderFuture = ProcessCameraProvider.getInstance(this) cameraProviderFuture.addListener(Runnable { // 用于将摄像机的生命周期绑定到生命周期所有者 val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() val preview = Preview.Builder() .build() .also { it.setSurfaceProvider(viewFinder.createSurfaceProvider()) } imageCapture = ImageCapture.Builder() .build() // 默认选择后置摄像头,这边可以设置方法选择摄像头 val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA try { cameraProvider.unbindAll() // 将用例绑定到相机 cameraProvider.bindToLifecycle( this, cameraSelector, preview, imageCapture) } catch(exc: Exception) { Log.e(TAG, “Use case binding failed”, exc) } }, ContextCompat.getMainExecutor(this)) } private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all { ContextCompat.checkSelfPermission( baseContext, it) == PackageManager.PERMISSION_GRANTED } //申请权限的方法 override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray) { if (requestCode == REQUEST_CODE_PERMISSIONS) { if (allPermissionsGranted()) { startCamera() } else { Toast.makeText(this, “Permissions not granted by the user.”, Toast.LENGTH_SHORT).show() finish() } } } private fun getOutputDirectory(): File { val mediaDir = externalMediaDirs.firstOrNull()?.let { File(it, resources.getString(R.string.app_name)).apply { mkdirs() } } return if (mediaDir != null && mediaDir.exists()) 欢迎分享,转载请注明来源:内存溢出
评论列表(0条)