概览

CameraX是一个Jetpack支持库,用来帮助开发者简化相机应用的开发和适配工作,它将一系列旧的Camera和新的Camera2的相机API进行统一适配,将两套设计迥异的相机API进行适配设计,并且作为androidX并作为Jetpack的一部分再发布,用来简化开发者开发相机功能时的大量重复适配的工作。最低可以适配到API Level 21。
由于加入到了Jetpack组件当中,它也增加了一部分功能用来绑定到LifecycleOwner等API来适配到生命周期接口的能力,使得开发者无需再重复编写生命周期相关的模板代码。

用例组件

CameraX内置了几个常用的用例,基类是UserCase
,从UserCase中派生出了以下三种使用场景:

  • 预览Preview :被用于显示预览,显示时会使用Surface展示预览,因此还有一个自定义View名为PreviewView来内部选择性使用SurfaceView或者TextureView来展现Surface的预览内容。
  • 图像分析ImageAnalyzeImageAnalyze 提供了一个接口ImageAnalysis.Analyzer用于在预览的同时可以获取图像缓冲区数据用于分析,比如机器学习、计算机视觉与图形学处理等等。
  • 图片拍摄ImageCaptureImageCapture提供了一个接口并在发生图片保存动作时进行回调。

首次使用

我们需要对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)
将相机对象绑定到生命周期接口上

最后一步通过ProcessCameraProviderPreviewView预览、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使用入门——相机预览相关推荐

  1. 2022-07-21 Android 相机预览数据转Bitmap优化

    背景 在Android开发中我们有时候会需要拿到相机预览数据转成bitmap自己做处理. 常用方式 在Android API中提供了 一套转换方式: private Bitmap convertBit ...

  2. android 摄像头花屏_关于Android 4.4相机预览、录像花屏的问题的解决方法

    关于Android 4.4相机预览.录像花屏的问题的解决方法 系统: lc android4.4 在做前后摄像头录像的时候,发现会出现花屏的时候,但不是必现,可能会在某一次重启之后会出现,而且出现之后 ...

  3. android自定义相机预览尺寸,相机在Android中,如何获得最佳尺寸,预览尺寸,图片尺寸,视图尺寸,图像扭曲...

    混合来自OpenGL和 Android相机的视图时图像失真,以便在使用takepicture方法时获取两者的图像.我查了一下,发现相机图片设置为640X480,openGL视图和相机预览都设置为128 ...

  4. 【Camera相机开发】实现相机预览

    文章目录 认识 Parameters 设置预览尺寸 添加预览 Surface 开启和关闭预览 校正预览画面方向 自然方向 设备方向 局部坐标系 屏幕方向 摄像头传感器方向 画面方向校正 适配预览比例 ...

  5. Android相机预览设置适配及显示方式

    Android相机的部分工作原理. 预览流程 相机预览是Android Camera最常用的功能之一,它是很多功能重要的输入,例如扫码.AR等. 一般而言,相机预览的整体流程,可以通过下图表示: 其中 ...

  6. android 预览和拍照成像方向不一致,Android相机预览方向深入探究

    原标题:Android相机预览方向深入探究 今日快讯 9月7日,北京市交通委召集各区管理部门和15家共享自行车企业负责人,听取共享自行车投放和管理的意见建议,研究决定并下发通知,暂停在本市新增投放共享 ...

  7. android从九宫格全屏预览,仿微信朋友圈展示图片的九宫格图片展示控件,支持点击图片全屏预览大图...

    AssNineGridView 仿微信朋友圈展示图片的九宫格图片展示控件,支持点击图片全屏预览大图(可自定义). 写在前面 这是一个九宫格控件,本来是很久之前就写好了,现在才开源出来,也是看了很多优秀 ...

  8. Android相机预览页面被压缩和拉伸问题

    最近公司要求在原有的项目中添加一个扫码登录的功能,在调试好相机之后,发现相机返回到Surfaceview页面上的预览图片,与我们现实中物品的比例并不相同,在一块正方形的Surfaceview中,预览界 ...

  9. qr码是二维码码_SwiftUI中的相机预览和QR码扫描仪

    qr码是二维码码 In this post, I will guide you through the creation of a QR-code scanner for iOS, using Swi ...

最新文章

  1. Webkit Flex伸缩盒模型属性备忘
  2. firewall添加白名单_firewall的规则设置与命令(白名单设置)
  3. 印度孟买机器人餐厅_宝莱坞机器人2.0:重生归来一起来看印度神片!
  4. jQuery轮 播的封装
  5. CodeForces - 1217F Forced Online Queries Problem(线段树分治+并查集撤销)
  6. 大咖微课 | 直面Angular2系列课第二期开讲
  7. java object转泛型_为什么Java的泛型要用擦除实现
  8. HTML 5 Canvas
  9. java的setbounds_java Swing组件setBounds()简单用法实例分析
  10. Java学习之面板与布局管理器
  11. SpringBlade 2.0-RC3 发布,全新的微服务开发平台
  12. Bootstrap优秀模板-INSPINIA.2.9.2
  13. 这游戏到底怎么了? 一年后,再看《刺客信条奥德赛》
  14. Mac版本的PS2017、2018、2019、2020 合集
  15. STM32显示软件取模图片
  16. 橡胶密封圈的作用和优点
  17. 如何配置 uboot
  18. mtk-disp开篇:名词扫盲
  19. win10下openssl生成证书过程
  20. 【CV】高被引行人重识别(Person Re-ID)综述论文

热门文章

  1. oracle数据库相关知识点,Oracle数据库小知识点整理
  2. Python实现秒杀抢购某宝商品,不再害怕双十一抢不到了
  3. Launcher组件启动MainActivity组件的过程
  4. UG NX2206 Build 1700 安装激活教程
  5. mkfs.minix.c之minix_super_block.s_ninodes获取解析
  6. jlink命令行操作
  7. NiN-网络中的网络(CNN卷积神经网络)
  8. GitHub中的readme.md
  9. ad 如何拖动实心区域的中间点
  10. hanlp词性对照表