试手一下CameraX(APP)

2024-03-04 01:44
文章标签 app 一下 试手 camerax

本文主要是介绍试手一下CameraX(APP),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

书接上回。

首先还是看谷歌的官方文档:

https://developer.android.com/media/camera/camerax?hl=zh-cn

https://developer.android.com/codelabs/camerax-getting-started?hl=zh-cn#1

注:这里大部分内容也来自谷歌文档。

官方文档用的是Kotlin,和Java也大差不差。看看流程就好。

API 级别设置为 21。

 

1 环境配置

 

在Gardle中增加依赖,我理解就是增加底层库,这几个应该就是camerax所使用的Framework的so,下面应该是AIDL调用的HAL。这个部分和底层驱动关系就很大了,后面还会单独写一篇。

dependencies {def camerax_version = "1.1.0-beta01"implementation "androidx.camera:camera-core:${camerax_version}"implementation "androidx.camera:camera-camera2:${camerax_version}"implementation "androidx.camera:camera-lifecycle:${camerax_version}"implementation "androidx.camera:camera-video:${camerax_version}"implementation "androidx.camera:camera-view:${camerax_version}"implementation "androidx.camera:camera-extensions:${camerax_version}"
}

同时要增加Java8和viewBinding的支持。

    compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}buildFeatures {viewBinding true}

在Layout的activity_main.xml中使用PreviewView。这个应该是camerax的控件。

   <androidx.camera.view.PreviewViewandroid:id="@+id/viewFinder"android:layout_width="match_parent"android:layout_height="match_parent" />

增加两个按键,分别是takephoto和capturevideo,并增加按键事件。

       // Set up the listeners for take photo and video capture buttonsviewBinding.imageCaptureButton.setOnClickListener { takePhoto() }viewBinding.videoCaptureButton.setOnClickListener { captureVideo() }

在AndroidManifest.xml中增加权限。

<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"android:maxSdkVersion="28" />

 在运行时会让你授权。

刚开始运行时,要检查权限。

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, 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()}}
}

2 CameraX调用代码

 主要用到的的几个包:

import androidx.camera.core.ImageCapture
import androidx.camera.video.Recorder
import androidx.camera.video.Recording
import androidx.camera.video.VideoCapture
2.1 提供图像预览:

大体的流程就是首先取得surface,然后使用cameraProvider.bindToLifecycle,将surface作为参数传进去。

private fun startCamera() {val cameraProviderFuture = ProcessCameraProvider.getInstance(this)cameraProviderFuture.addListener({// Used to bind the lifecycle of cameras to the lifecycle ownerval cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()// Previewval preview = Preview.Builder().build().also {it.setSurfaceProvider(viewBinding.viewFinder.surfaceProvider)}// Select back camera as a defaultval cameraSelector = CameraSelector.DEFAULT_BACK_CAMERAtry {// Unbind use cases before rebindingcameraProvider.unbindAll()// Bind use cases to cameracameraProvider.bindToLifecycle(this, cameraSelector, preview)} catch(exc: Exception) {Log.e(TAG, "Use case binding failed", exc)}}, ContextCompat.getMainExecutor(this))
}
2.2 拍照:

可以看到,基本上就是围绕着imageCapture.takePicture这个方法。name,contentValues,outputOptions都是作为参数传进去。

private fun takePhoto() {// Get a stable reference of the modifiable image capture use caseval imageCapture = imageCapture ?: return// Create time stamped name and MediaStore entry.val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis())val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME, name)put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")}}// Create output options object which contains file + metadataval outputOptions = ImageCapture.OutputFileOptions.Builder(contentResolver,MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues).build()// Set up image capture listener, which is triggered after photo has// been takenimageCapture.takePicture(outputOptions,ContextCompat.getMainExecutor(this),object : ImageCapture.OnImageSavedCallback {override fun onError(exc: ImageCaptureException) {Log.e(TAG, "Photo capture failed: ${exc.message}", exc)}override funonImageSaved(output: ImageCapture.OutputFileResults){val msg = "Photo capture succeeded: ${output.savedUri}"Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()Log.d(TAG, msg)}})
}
2.3 拍视频:

基本就是围绕着videoCapture.output。name,contentValues,mediaStoreOutputOptions都是作为参数使用。在output中,好像是使用了lambda函数,弄了一些内置行为。

// Implements VideoCapture use case, including start and stop capturing.
private fun captureVideo() {val videoCapture = this.videoCapture ?: returnviewBinding.videoCaptureButton.isEnabled = falseval curRecording = recordingif (curRecording != null) {// Stop the current recording session.curRecording.stop()recording = nullreturn}// create and start a new recording sessionval name = SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis())val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME, name)put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/CameraX-Video")}}val mediaStoreOutputOptions = MediaStoreOutputOptions.Builder(contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI).setContentValues(contentValues).build()recording = videoCapture.output.prepareRecording(this, mediaStoreOutputOptions).apply {if (PermissionChecker.checkSelfPermission(this@MainActivity,Manifest.permission.RECORD_AUDIO) ==PermissionChecker.PERMISSION_GRANTED){withAudioEnabled()}}.start(ContextCompat.getMainExecutor(this)) { recordEvent ->when(recordEvent) {is VideoRecordEvent.Start -> {viewBinding.videoCaptureButton.apply {text = getString(R.string.stop_capture)isEnabled = true}}is VideoRecordEvent.Finalize -> {if (!recordEvent.hasError()) {val msg = "Video capture succeeded: " +"${recordEvent.outputResults.outputUri}"Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()Log.d(TAG, msg)} else {recording?.close()recording = nullLog.e(TAG, "Video capture ends with error: " +"${recordEvent.error}")}viewBinding.videoCaptureButton.apply {text = getString(R.string.start_capture)isEnabled = true}}}}
}

好了,就到这了。先概要看看就行了。

这篇关于试手一下CameraX(APP)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/771629

相关文章

【详细介绍一下GEE】

GEE(Google Earth Engine)是一个强大的云计算平台,它允许用户处理和分析大规模的地球科学数据集,如卫星图像、气候模型输出等。以下是对GEE用法的详细介绍: 一、平台访问与账户设置 访问GEE平台: 用户可以通过访问Google Earth Engine的官方网站来开始使用GEE。 创建账户: 用户需要注册并登录Google账户,然后申请访问GEE平台。申请过程可能需要提

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

ConstraintLayout布局里的一个属性app:layout_constraintDimensionRatio

ConstraintLayout 这是一个约束布局,可以尽可能的减少布局的嵌套。有一个属性特别好用,可以用来动态限制宽或者高app:layout_constraintDimensionRatio 关于app:layout_constraintDimensionRatio参数 app:layout_constraintDimensionRatio=“h,1:1” 表示高度height是动态变化

App Store最低版本要求汇总

1,自此日期起: 2024 年 4 月 29 日 自 2024 年 4 月 29 日起,上传到 App Store Connect 的 App 必须是使用 Xcode 15 为 iOS 17、iPadOS 17、Apple tvOS 17 或 watchOS 10 构建的 App。将 iOS App 提交至 App Store - Apple Developer 2,最低XCode版本 Xcod

鸿蒙自动化发布测试版本app

创建API客户端 API客户端是AppGallery Connect用于管理用户访问AppGallery Connect API的身份凭据,您可以给不同角色创建不同的API客户端,使不同角色可以访问对应权限的AppGallery Connect API。在访问某个API前,必须创建有权访问该API的API客户端。 1.登录AppGallery Connect网站,选择“用户与访问”。选择左侧

Xinstall助力App全渠道统计,参数传递下载提升用户体验!

在移动互联网时代,App已成为我们日常生活中不可或缺的一部分。然而,对于App开发者来说,如何有效地推广和运营自己的应用,却是一个不小的挑战。尤其是在面对众多渠道、复杂的数据统计和用户需求多样化的情况下,如何精准地触达目标用户,提升用户的下载、安装和活跃度,更是考验着每一个运营者的智慧。 今天,我们就来揭秘一个能够帮助App开发者解决这些痛点的神器——Xinstall。作为一家一站式App全渠道

Flask 创建app 时候传入的 static_folder 和 static_url_path参数理解

Flask 在创建app的时候 是用 app = Flask(__name__) 来创建的,不传入 static_folder参数的话 ,默认的静态文件的位置是在 static目录下 我们可以进入 Flask的源码里面查看 ctrl+鼠标左键进入 这是Flask的 __init__源码(后面还有一些,我就选了需要的代码)     def __init__(self,import_

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArra

这个错误说的是一个不可变数组负值给了一个可变的数组。有可能你前面定义的数组是一个可变数组,但是在你其他方法里面用他的时候,他就是一个不可变数组,因为在可变数组拿到别的地方用的时候,他会默认为不可变的,可能这只是一个类里面你只是简单的声明了他吧,并没有进行对他初始化,或者分配什么内存,所以他只是一个不可变的数组,当你在其他地方用他的时候,他就默认为不可变的数组,他可能因为你的没分配内存,而变回不可变

app提交到腾讯开发平台,提示无法获取签名信息,请上传有效包(110506)

最近提交APP时遇到的,一般情况下是因为打包时至勾选v2没有勾选v1的原因,如下图: 这个时候将v1勾选即可。 但是在打包时ˉv1和v2都勾选了也可能会出现这个报错,那就要看一下gradle的 minSdkVersion,如果这个版本在24-26之间也可能会提示这个错误,所以降低这个版本就可以了

基于Python的电商导购APP设计与实现

基于Python的电商导购APP设计与实现 Design and Implementation of an E-commerce Shopping Guide App based on Python 完整下载链接:基于Python的电商导购APP设计与实现 文章目录 基于Python的电商导购APP设计与实现摘要第一章 简介1.1 研究背景1.2 研究目的1.3 研究方法1.4 论文结