本文主要是介绍Jetpack CameraX,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- Jetpack CameraX
- 概述
- 添加依赖库
- 使用
- 预览
- 拍照
- 录视频
- 代码下载
- 文档
Jetpack CameraX
概述
CameraX 是一个 Jetpack 库,旨在帮助您更轻松地开发相机应用。如果您要开发新应用,我们建议您从 CameraX 开始。它提供了一个一致且易于使用的 API,该 API 适用于绝大多数 Android 设备,并向后兼容 Android 5.0(API 级别 21)。
添加依赖库
// CameraX core library using the camera2 implementation
def camerax_version = "1.2.0-alpha02" //1.2.0-alpha02
// The following line is optional, as the core library is included indirectly by camera-camera2
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
// If you want to additionally use the CameraX Lifecycle library
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
// If you want to additionally use the CameraX VideoCapture library
implementation "androidx.camera:camera-video:${camerax_version}"
// If you want to additionally use the CameraX View class
implementation "androidx.camera:camera-view:${camerax_version}"
// If you want to additionally add CameraX ML Kit Vision Integration
implementation "androidx.camera:camera-mlkit-vision:${camerax_version}"
// If you want to additionally use the CameraX Extensions library
implementation "androidx.camera:camera-extensions:${camerax_version}"
使用
预览
class PictureActivity : BaseActivity() {private lateinit var mBinding: ActivityPictureBindingprivate lateinit var mPreview: Previewprivate lateinit var mCamera: Cameraprivate lateinit var mCameraProvider: ProcessCameraProviderprivate var singleTapDetector: GestureDetector? = nullprivate val mExecutor: Executor by lazy {ContextCompat.getMainExecutor(this)}private var isBack = trueoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)mBinding = ActivityPictureBinding.inflate(layoutInflater)setContentView(mBinding.root)mBinding.root.post {initCameraX()}}private fun initCameraX() {// 请求CameraProviderval cameraProviderFuture = ProcessCameraProvider.getInstance(this)cameraProviderFuture.addListener({mCameraProvider = cameraProviderFuture.get()bindPreview(mCameraProvider, mBinding.previewView)listenGesture()}, mExecutor)}private fun bindPreview(cameraProvider: ProcessCameraProvider, previewView: PreviewView) {// 切换前后摄像头val cameraSelector =if (isBack) CameraSelector.DEFAULT_BACK_CAMERA else CameraSelector.DEFAULT_FRONT_CAMERA// 创建PreviewmPreview = Preview.Builder().build() // 绑定前确保解除了所有绑定,防止CameraProvider重复绑定到Lifecycle发生异常cameraProvider.unbindAll()// 绑定生命周期mCamera = cameraProvider.bindToLifecycle(this,cameraSelector,mPreview)// 将Preview连接到PreviewViewmPreview.setSurfaceProvider(previewView.surfaceProvider)}/*** 监听手势*/private fun listenGesture() {mBinding.previewView.setOnTouchListener { view, event ->singleTapForFocus(event)true}focusOnPosition((mBinding.previewView.width / 2).toFloat(),(mBinding.previewView.height / 2).toFloat(),)}/*** 根据坐标聚焦*/private fun focusOnPosition(x: Float, y: Float, isShowTapView: Boolean = false) {logE("position: $x - $y")logE("width: ${mBinding.previewView.width} height: ${mBinding.previewView.height}")val action = FocusMeteringAction.Builder(mBinding.previewView.meteringPointFactory.createPoint(x, y)).build()if (isShowTapView) {showTapView(x.toInt(), y.toInt())}mCamera.cameraControl.startFocusAndMetering(action)}/*** 显示聚焦的图标*/private fun showTapView(x: Int, y: Int) {val imageView = ImageView(this).apply {setImageResource(R.drawable.ic_focus_view)}val popupWindow = PopupWindow(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT).apply {contentView = imageView}val offset = dp2px(50)popupWindow.showAsDropDown(mBinding.previewView, x - offset / 2, y - offset / 2)mBinding.previewView.postDelayed({ popupWindow.dismiss() }, 500L)}/*** 单击聚焦*/private fun singleTapForFocus(event: MotionEvent) {if (singleTapDetector == null) {singleTapDetector = GestureDetector(this@PictureActivity,object : GestureDetector.SimpleOnGestureListener() {override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {focusOnPosition(event.x, event.y, true)return super.onSingleTapConfirmed(e)}})}singleTapDetector!!.onTouchEvent(event)}/*** 前后摄像头切换*/private fun changeCamera() {isBack = !isBackbindPreview(mCameraProvider, mBinding.previewView)}
}
拍照
// 设置图片拍摄
mImageCapture = ImageCapture.Builder().setTargetRotation(previewView.display.rotation)
// .setCaptureMode() // 设置拍摄模式
// .setFlashMode() // 设置闪光模式.build()// 设置图片质量
mImageAnalysis = ImageAnalysis.Builder().setTargetRotation(previewView.display.rotation).setTargetResolution(Size(720, 1440)).setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build()// 绑定生命周期
mCamera = cameraProvider.bindToLifecycle(this,cameraSelector,mPreview,mImageCapture,mImageAnalysis
)
// 拍照
val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME,"my_capture_${System.currentTimeMillis()}")put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")}
val outputFileOptions = ImageCapture.OutputFileOptions.Builder(contentResolver,MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues
).build()
mImageCapture.takePicture(outputFileOptions,mExecutor,object : ImageCapture.OnImageSavedCallback {override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {val uri = outputFileResults.savedUri ?: returnshowPicture(uri)}override fun onError(exception: ImageCaptureException) {logE("onError: ${exception.imageCaptureError}")}})
录视频
class VideoActivity : BaseActivity() {private lateinit var mBinding: ActivityVideoBindingprivate lateinit var mPreview: Previewprivate lateinit var mCamera: Cameraprivate lateinit var mCameraProvider: ProcessCameraProviderprivate lateinit var mVideoCapture: VideoCaptureprivate val mExecutor: Executor by lazy {ContextCompat.getMainExecutor(mContext)}private var isRecording = falseoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)mBinding = ActivityVideoBinding.inflate(layoutInflater)setContentView(mBinding.root)mBinding.root.post {initCameraX()}mBinding.ivVideo.setOnClickListener {if (!isRecording) startRecordVideo() else stopRecordVideo()}}private fun initCameraX() {val listenableFuture = ProcessCameraProvider.getInstance(this)listenableFuture.addListener({mCameraProvider = listenableFuture.get()bindPreview(mCameraProvider, mBinding.previewView)}, mExecutor)}private fun bindPreview(cameraProvider: ProcessCameraProvider, previewView: PreviewView) {// 设置摄像头val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA// 创建PreviewmPreview = Preview.Builder().build()mVideoCapture = VideoCapture.Builder().setTargetRotation(previewView.display.rotation).setVideoFrameRate(25).setBitRate(3 * 1024 * 1024).build()// 绑定前确保解除了所有绑定,防止CameraProvider重复绑定到Lifecycle发生异常cameraProvider.unbindAll()// 绑定生命周期mCamera = cameraProvider.bindToLifecycle(this,cameraSelector,mPreview,mVideoCapture)// 将Preview连接到PreviewViewmPreview.setSurfaceProvider(previewView.surfaceProvider)}private fun startRecordVideo() {isRecording = truemBinding.tvVideo.text = "停止录制"val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME, "my_video" + "_" + System.currentTimeMillis())put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")}val options = VideoCapture.OutputFileOptions.Builder(contentResolver,MediaStore.Video.Media.EXTERNAL_CONTENT_URI,contentValues).build()if (ActivityCompat.checkSelfPermission(this,Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {return}mVideoCapture.startRecording(options,mExecutor,object : VideoCapture.OnVideoSavedCallback {override fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {val uri = outputFileResults.savedUriuri?.let {val path = it.pathpath?.let {showToast("视频保存在:$path")logE("视频保存在:$path")}}}override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {showToast("保存失败:$message")logE("保存失败:$message")}})}private fun stopRecordVideo() {isRecording = falsemBinding.tvVideo.text = "开始录制"mVideoCapture.stopRecording()}
}
代码下载
文档
https://juejin.cn/post/7267840969605382198
https://juejin.cn/post/6951017751457005576
https://blog.csdn.net/EthanCo/article/details/125603671
https://developer.android.google.cn/media/camera/camerax?hl=zh-cn
这篇关于Jetpack CameraX的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!