Jetpack支持库CameraX使用入门——相机预览
概览
CameraX是一个Jetpack支持库,用来帮助开发者简化相机应用的开发和适配工作,它将一系列旧的Camera和新的Camera2的相机API进行统一适配,将两套设计迥异的相机API进行适配设计,并且作为androidX并作为Jetpack的一部分再发布,用来简化开发者开发相机功能时的大量重复适配的工作。最低可以适配到API Level 21。
由于加入到了Jetpack组件当中,它也增加了一部分功能用来绑定到LifecycleOwner等API来适配到生命周期接口的能力,使得开发者无需再重复编写生命周期相关的模板代码。
用例组件
CameraX内置了几个常用的用例,基类是UserCase
,从UserCase
中派生出了以下三种使用场景:
- 预览
Preview
:被用于显示预览,显示时会使用Surface展示预览,因此还有一个自定义View名为PreviewView
来内部选择性使用SurfaceView
或者TextureView
来展现Surface的预览内容。 - 图像分析
ImageAnalyze
:ImageAnalyze
提供了一个接口ImageAnalysis.Analyzer
用于在预览的同时可以获取图像缓冲区数据用于分析,比如机器学习、计算机视觉与图形学处理等等。 - 图片拍摄
ImageCapture
:ImageCapture
提供了一个接口并在发生图片保存动作时进行回调。
首次使用
我们需要对build.gradle文件进行一定的修改:
我们用到了Kotlin语言,我们需要引入Kotlin语言包,
语言版本:
ext.kotlin_version = '1.5.21'
ext.java_version = JavaVersion.VERSION_1_8
添加Kotlin语言标准库和android支持:
dependencies {// Kotlin langimplementation 'androidx.core:core-ktx:1.6.0'implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
}
我们需要引入CameraX相关的包
dependencies {// CameraX 核心库def camerax_version = '1.0.1'implementation "androidx.camera:camera-core:$camerax_version"// CameraX Camera2 扩展包implementation "androidx.camera:camera-camera2:$camerax_version"// CameraX Lifecycle 生命周期框架支持implementation "androidx.camera:camera-lifecycle:$camerax_version"// CameraX View 用于预览的Viewimplementation 'androidx.camera:camera-view:1.0.0-alpha27'
}
预览用例
仅仅对于相机的预览来说,我们用到的类组件由以下几个类即可,不需要使用到Camera类。
Step 1:
首先我们先布局一个可预览的PreviewView。这个View是已经在androidx.camera中预置的自定义View:
<FrameLayoutandroid:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.camera.view.PreviewViewandroid:id="@+id/previewView"android:layout_width="match_parent"android:layout_height="match_parent" />
</FrameLayout>
由于这个View已经包含了SurfaceView或TextureView,我们无需再考虑处理这部分的逻辑。
Step 2:
我们通过ProcessCameraProvider.getInstance(this)
得到一个线程池的一个可等待对象,这个类型是ListenableFuture<ProcessCameraProvider>
,
lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
cameraProviderFuture = ProcessCameraProvider.getInstance(this)
然后在这个延迟等待对象中执行代码,并且运行在主线程Looper的Handler中。
cameraProviderFuture.addListener({}, ContextCompat.getMainExecutor(this))
Step 3:
我们获取ProcessCameraProvider
,用于获取Camera
并且绑定Surface到PreviewView上。
cameraProviderFuture.addListener({val cameraProvider = cameraProviderFuture.get()//在这里绑定PreviewbindPreview(cameraProvider)
}, ContextCompat.getMainExecutor(this))
bindPreview
的函数定义如下:
fun bindPreview(cameraProvider: ProcessCameraProvider) {var preview: Preview = Preview.Builder().build()var cameraSelector =CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()val previewView = findViewById<PreviewView>(R.id.previewView)preview.setSurfaceProvider(previewView.surfaceProvider)cameraProvider.bindToLifecycle(this, cameraSelector, preview)
}
拆解一下这个函数每一句话的作用:
构建一个Preview用例
var preview: Preview = Preview.Builder().build()
选择摄像头
CameraSelector.LENS_FACING_BACK
表示请求的镜头朝向是后置的,
CameraSelector.LENS_FACING_BACK
表示请求的镜头朝向是前置的。
var cameraSelector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()
绑定PreviewView
Preview要显示预览内容必须将其与PreviewView中的SurfaceView或Texture的Surface绑定。
Preview.setSurfaceProvider(SurfaceProvider)
方法承担了这个最主要的工作。
val previewView = findViewById<PreviewView>(R.id.previewView)
preview.setSurfaceProvider(previewView.surfaceProvider)
将相机对象绑定到生命周期接口上
最后一步通过ProcessCameraProvider
将PreviewView预览、Preview用例、CameraSelector相机选择对象
统合并且绑定。
cameraProvider.bindToLifecycle(this, cameraSelector, preview)
ProcessCameraProvider.bindToLifecycle()的最后一个参数是可变长度参数,可以传入多个UseCase的实现类,比如同时传入Preview的用例和ImageCapture的用例,实现预览并拍照的功能。如果加入ImageAnalyze还可以对缓冲区进行分析和其他操作。
一个DemoActivity的代码
这样就可以通过CameraX简化并且自动化选择相机参数显示相机预览,代码十分精简:
class DemoActivity : AppCompatActivity() {private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_demo)cameraProviderFuture = ProcessCameraProvider.getInstance(this)cameraProviderFuture.addListener({val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()//在这里绑定PreviewbindPreview(cameraProvider)}, ContextCompat.getMainExecutor(this))}fun bindPreview(cameraProvider: ProcessCameraProvider) {var preview: Preview = Preview.Builder().build()var cameraSelector: CameraSelector =CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()val previewView = findViewById<PreviewView>(R.id.previewView)preview.setSurfaceProvider(previewView.surfaceProvider)cameraProvider.bindToLifecycle(this, cameraSelector, preview)}
}
然而其内部判断是SurfaceView还是TextureView呢?PreviewView类中给出了一段代码
static boolean shouldUseTextureView(@NonNull SurfaceRequest surfaceRequest,@NonNull final ImplementationMode implementationMode) {// TODO(b/159127402): use TextureView if target rotation is not display rotation.boolean isLegacyDevice = surfaceRequest.getCamera().getCameraInfoInternal().getImplementationType().equals(CameraInfo.IMPLEMENTATION_TYPE_CAMERA2_LEGACY);boolean hasSurfaceViewQuirk = DeviceQuirks.get(SurfaceViewStretchedQuirk.class) != null;if (surfaceRequest.isRGBA8888Required() || Build.VERSION.SDK_INT <= 24 || isLegacyDevice|| hasSurfaceViewQuirk) {// Force to use TextureView when the device is running android 7.0 and below, legacy// level, RGBA8888 is required or SurfaceView has quirks.return true;}switch (implementationMode) {case COMPATIBLE:return true;case PERFORMANCE:return false;default:throw new IllegalArgumentException("Invalid implementation mode: " + implementationMode);}}
看得出来其给出了4个条件,只要符合其一就使用TextureView,并且通过可以通过手动设定模式来强制选择。
我们看一下这四个条件:
- 1、如果这个设备是较老的设备,只要判定在Android 7.0以下;
- 2、如果摄像头支持级别是旧的级别;
- 3、如果摄像头请求要求的色彩空间是RGB8888时;
- 4、设备厂商的兼容性问题
除此以外都使用SurfaceView。因此我们可以看出来,Android团队是多么偏爱SurfaceView。
当对PreviewView选择了特定实现模式是COMPATIBLE
时,也是使用TextureView,选择实现模式是PERFORMANCE
时,使用SurfaceView
,并且使得以上4个条件失效。
Jetpack支持库CameraX使用入门——相机预览相关推荐
- 2022-07-21 Android 相机预览数据转Bitmap优化
背景 在Android开发中我们有时候会需要拿到相机预览数据转成bitmap自己做处理. 常用方式 在Android API中提供了 一套转换方式: private Bitmap convertBit ...
- android 摄像头花屏_关于Android 4.4相机预览、录像花屏的问题的解决方法
关于Android 4.4相机预览.录像花屏的问题的解决方法 系统: lc android4.4 在做前后摄像头录像的时候,发现会出现花屏的时候,但不是必现,可能会在某一次重启之后会出现,而且出现之后 ...
- android自定义相机预览尺寸,相机在Android中,如何获得最佳尺寸,预览尺寸,图片尺寸,视图尺寸,图像扭曲...
混合来自OpenGL和 Android相机的视图时图像失真,以便在使用takepicture方法时获取两者的图像.我查了一下,发现相机图片设置为640X480,openGL视图和相机预览都设置为128 ...
- 【Camera相机开发】实现相机预览
文章目录 认识 Parameters 设置预览尺寸 添加预览 Surface 开启和关闭预览 校正预览画面方向 自然方向 设备方向 局部坐标系 屏幕方向 摄像头传感器方向 画面方向校正 适配预览比例 ...
- Android相机预览设置适配及显示方式
Android相机的部分工作原理. 预览流程 相机预览是Android Camera最常用的功能之一,它是很多功能重要的输入,例如扫码.AR等. 一般而言,相机预览的整体流程,可以通过下图表示: 其中 ...
- android 预览和拍照成像方向不一致,Android相机预览方向深入探究
原标题:Android相机预览方向深入探究 今日快讯 9月7日,北京市交通委召集各区管理部门和15家共享自行车企业负责人,听取共享自行车投放和管理的意见建议,研究决定并下发通知,暂停在本市新增投放共享 ...
- android从九宫格全屏预览,仿微信朋友圈展示图片的九宫格图片展示控件,支持点击图片全屏预览大图...
AssNineGridView 仿微信朋友圈展示图片的九宫格图片展示控件,支持点击图片全屏预览大图(可自定义). 写在前面 这是一个九宫格控件,本来是很久之前就写好了,现在才开源出来,也是看了很多优秀 ...
- Android相机预览页面被压缩和拉伸问题
最近公司要求在原有的项目中添加一个扫码登录的功能,在调试好相机之后,发现相机返回到Surfaceview页面上的预览图片,与我们现实中物品的比例并不相同,在一块正方形的Surfaceview中,预览界 ...
- qr码是二维码码_SwiftUI中的相机预览和QR码扫描仪
qr码是二维码码 In this post, I will guide you through the creation of a QR-code scanner for iOS, using Swi ...
最新文章
- Webkit Flex伸缩盒模型属性备忘
- firewall添加白名单_firewall的规则设置与命令(白名单设置)
- 印度孟买机器人餐厅_宝莱坞机器人2.0:重生归来一起来看印度神片!
- jQuery轮 播的封装
- CodeForces - 1217F Forced Online Queries Problem(线段树分治+并查集撤销)
- 大咖微课 | 直面Angular2系列课第二期开讲
- java object转泛型_为什么Java的泛型要用擦除实现
- HTML 5 Canvas
- java的setbounds_java Swing组件setBounds()简单用法实例分析
- Java学习之面板与布局管理器
- SpringBlade 2.0-RC3 发布,全新的微服务开发平台
- Bootstrap优秀模板-INSPINIA.2.9.2
- 这游戏到底怎么了? 一年后,再看《刺客信条奥德赛》
- Mac版本的PS2017、2018、2019、2020 合集
- STM32显示软件取模图片
- 橡胶密封圈的作用和优点
- 如何配置 uboot
- mtk-disp开篇:名词扫盲
- win10下openssl生成证书过程
- 【CV】高被引行人重识别(Person Re-ID)综述论文
热门文章
- oracle数据库相关知识点,Oracle数据库小知识点整理
- Python实现秒杀抢购某宝商品,不再害怕双十一抢不到了
- Launcher组件启动MainActivity组件的过程
- UG NX2206 Build 1700 安装激活教程
- mkfs.minix.c之minix_super_block.s_ninodes获取解析
- jlink命令行操作
- NiN-网络中的网络(CNN卷积神经网络)
- GitHub中的readme.md
- ad 如何拖动实心区域的中间点
- hanlp词性对照表