Android JetPack组件-CameraX初探

摘要:
CameraX是谷歌推出的另一个JetPack组件。这是一个新的小工具,所以我想分享我使用这个项目的经验。。谷歌开发人员对CameraX的评论如下:CameraX是一个Jetpack支持库,旨在帮助您简化相机应用程序的开发。项目中CameraX的使用基于Camera2,内部实现细节与谷歌之前推出的Camera2非常相似,因此之前使用过Camera2的朋友可能会对CameraX产生亲切感。朋友们,相信我,CameraX的介绍真的很简单,很简单,非常简单。我们需要单独配置它们,并告诉CameraX如何使用它们。

CameraX 又是一个 Google 推出的 JetPack 组件 ,是一个新鲜玩意儿,故给大家分享下我在项目中的使用过程心得。。

CameraX 是什么?

Google 开发者文档 对 CameraX 的评价如下:

CameraX是一个Jetpack支持库,旨在帮助您简化相机应用程序的开发工作。它提供一致且易于使用的API接口,适用于大多数Android设备,可以向后兼容至Android 5.0(API等级21)。

虽然它利用的是camera2的功能,但使用的是更为简单且基于用例的方法,该方法具有生命周期感知能力。它还解决了设备兼容性问题,因此您无需在代码库中包含设备专有代码。这些功能减少了将相机功能添加到应用时需要编写的代码量。

最后,通过CameraX,开发者只需两行代码即可利用与预安装的相机应用相同的相机体验和功能 CameraX扩展 是可选插件,通过该插件,您可以在支持的设备上向自己的应用中添加人像,HDR,夜间模式和美颜等效果。

本人的愚见:CameraX 是 Google 为了解决开发者们开发有关相机功能时遇到诸如适配等各种问题的一件称手的兵器。。

CameraX 入门

CameraX 还在测试alpha阶段,截至目前核心库最新的版本是 1.0.0-alpha05,估计Google未来会继续修复现有的bug和推出稳定版(我也不知道啥时候?)。
在这里插入图片描述

CameraX 在项目中使用

CameraX 是 基于 Camera2 构建的,内部实现细节很多与Google之前推出的Camera2相同,所以说之前使用过Camera2 的旁友们对于 CameraX 可能会有一种亲切感hhh。而对于没有接触过Camera2或者说没有接触过相机功能开发的小?伴们,相信我,CameraX 入门的确是很简单,很简单,很简单。

有关下面的代码是用 Java 实现的,相信使用 Kotlin的小伙伴,也能一看就懂,网上的资料也大部分是Kotlin的?

CameraX 依赖

首先是要在 build.gradle(Module:app) 添加 以下的依赖,可以根据具体的需求添加?

	// CameraX 核心库
    def camerax_version = "1.0.0-alpha05"
    // CameraX view 
    def camerax_view_version = "1.0.0-alpha02"
    // CameraX 扩展 library
    def camerax_ext_version = "1.0.0-alpha02"
    implementation "androidx.camera:camera-core:$camerax_version"
    //如果你要使用Camera2的扩展功能
    implementation "androidx.camera:camera-camera2:$camerax_version"
    // 如果你要使用 CameraX View
    implementation "androidx.camera:camera-view:$camerax_view_version"
    // 如果你要使用 CameraX 的 扩展功能
    implementation "androidx.camera:camera-extensions:$camerax_ext_version"
    //申请权限
    implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5'

CameraX 获取权限

使用CameraX还是需要我们声明和动态申请的,毕竟我们还是会使用相机这个东西。

1、在 AndroidManifest.xml 里 注册相关的权限,相信大家都懂的~

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.permission.camera"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

2、在你的项目中合适的地方,动态申请下相关的权限

为了方便省事,我使用了 RxPermissons 这个库进行动态申请权限和权限的管理

@SuppressLint("CheckResult")
    public void initPermission() {
RxPermissions rxPermissions = new RxPermissions(this);     		

          rxPermissions.request(   
                       Manifest.permission.CAMERA, 		        
                       Manifest.permission.WRITE_EXTERNAL_STORAGE,  
                       Manifest.permission.READ_EXTERNAL_STORAGE)
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {
                        if (aBoolean) {
                           //申请权限成功,操作
                        } else {
                           //申请权限失败,操作
                        }
                    }
                });
    }

页面布局

众所周知,无论是拍照前还是拍摄视频,我们都希望可以看到当前的预览,从而控制拍摄的效果,那么CameraX是通过啥东东来让我们进行预览操作的呢?答案是 它的 TextureView ,我们需要在进行预览的页面的布局XML里放入一个 TextureView

    <RelativeLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <TextureView
            android: 
            android:layout_width="match_parent"
            android:fitsSystemWindows="true"
            android:layout_height="match_parent"
            />
    </RelativeLayout>

那么预览的输出到时候就会在这个 TextureView上展示出来。

重头戏来了,怎么让相机打开看到图像并且可以保存拍摄的照片呢

1、 CameraX 的配置 (告诉 CameraX ,你想要做什么)

CameraX 可以做的事情,总体来说分三个部分–图像预览PreView,图像分析Analyze,图像拍摄Capture。

我们要分别对它们进行配置,告诉 CameraX 我们要怎么用它们。

ImageCapture类、ImageAnalysis类、Preview类的对象就是我们具体操作使用的对象

配置过程如下:

    ImageCapture imageCapture;
    ImageAnalysis imageAnalysis;
    Preview preview;
    
    void initCameraConfig() {
         //拍摄预览的配置config
         PreviewConfig.Builder configBuilder = new PreviewConfig.Builder().setLensFacing(CameraX.LensFacing.BACK);
         preview = new Preview(configBuilder.build());
         //图片分析的配置config,Size对象里面分辨率,CameraX会自动找最适合当前设备的分辨率
        ImageAnalysisConfig imageAnalysisConfig = new ImageAnalysisConfig.Builder().setTargetResolution(new Size(1080,2248)).build();
        imageAnalysis = new ImageAnalysis(imageAnalysisConfig);
        //图片拍摄的配置config
		ImageCaptureConfig.Builder captureBuilder = new ImageCaptureConfig.Builder().setLensFacing(CameraX.LensFacing.BACK);
        imageCapture = new ImageCapture(captureBuilder.build());
    }

2、如何使用ImageCapture类、ImageAnalysis类、Preview类的对象呢?

首先要把它们加入到 LifeCycle上管理

CameraX.bindToLifecycle(getSelf(), preview, imageAnalysis, imageCapture);

然后为它们注册绑定相关的事件

首先是 图像预览 和 图像分析 的事件

		//图像预览的具体操作
        preview.setOnPreviewOutputUpdateListener(new        			  Preview.OnPreviewOutputUpdateListener() {
            @Override
            public void onUpdated(Preview.PreviewOutput output) {
        	   //下面这一步很重要
        	   //把预览的输出附加在自己的TextureView控件上,这样才可以看见预览
              containerCamera.setSurfaceTexture(output.getSurfaceTexture());
            }
        });
        
		//图像分析的具体操作
        imageAnalysis.setAnalyzer(new ImageAnalysis.Analyzer() {
            @Override
            public void analyze(ImageProxy image, int rotationDegrees) {
            	// image 会不断传进来,你可以对它进行各种你想要的操作
            }
        });
       

拍摄、保存照片的操作比上面的多了一丢丢,不过也是灰常简单的!

            //创建要存储照片的File,要记得检查权限的获取
            String imageName = "QG7777777.png";
            //下面是拍摄照片的输出与回调,可以绑定一个按钮的点击事件之类的
			imageCapture.takePicture(createImageFile(imageName), new 	ImageCapture.OnImageSavedListener() {
                @SuppressLint("CheckResult")
                @Override
                public void onImageSaved(@NonNull File file) {
					//成功保存照片后的回调
                }
                
                @Override
                public void onError(@NonNull ImageCapture.ImageCaptureError imageCaptureError, @NonNull String message, @Nullable Throwable cause) {
                   //保存照片失败后的回调
                    String errorMsg = "发生了未知的错误";
                    if(cause != null) {
                        errorMsg = cause.getMessage();
                    }
                }
            });
            
     //保存指定名称的文件,绝对路径为"/storage/emulated/0/"+imageName
     File createImageFile(String imageName) {
        return new File(Environment.getExternalStorageDirectory(),imageName);
    }

好啦,按步骤做到这里,你已经可以拍摄出一张由CameraX 拍摄的照片了。

还不够,想要更多的基础操作?

CameraX 也支持很多的基础操作,下面以 1.0.0-alpha05 已经支持的 点击对焦 操作为例

CameraX 将对焦操作,(我认为的) 浓缩成了三步:

1、获取用户点击画面区域的屏幕坐标

2、将屏幕坐标系的坐标转换为CameraX能读懂的坐标

3、告诉CameraX ,你想要开启点击对焦操作(配置)

对焦操作很简单,获取点击画面区域的坐标方法很多很多,我的代码,参考如下:

        /**
         *点击画面区域进行对焦操作的实现
         */
containerCamera.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                TextureViewMeteringPointFactory pointFactory = new TextureViewMeteringPointFactory(containerCamera);
                MeteringPoint meteringPoint = pointFactory.createPoint(event.getX(),event.getY());
                FocusMeteringAction action = FocusMeteringAction.Builder
                        .from(meteringPoint)
                        .build();
                try { CameraX.getCameraControl(CameraX.LensFacing.BACK).startFocusAndMetering(action);
                } catch (CameraInfoUnavailableException e) {
                    e.printStackTrace();
                }
                return false;
            }
        });

扩展功能,Extensions ?

没错,CameraX 还支持 很多 扩展的功能,诸如开启 HDR ,开启 人像 模式,开启 **美颜模式 **等等等。。

CameraX 将扩展功能的开启 也 大大浓缩了,而且会自动判断设备是否支持开启。o( ̄▽ ̄)d

下面以开启 HDR 为例,让我们回到 配置 config 那一块

首先检查自己的 build.gradle(Module:app) 有没有 CameraX extensions 插件的依赖,没有的先补上。

在创建preview 和 imageCapture 对象的时候就把 我们想要 开启HDR 操作 告诉 CameraX,它就会帮我们检测设备是否支持并开启HDR这个功能了。

就是这么地简单,没有了以前的繁琐操作和适配问题。。

		//拍摄预览的配置config
         PreviewConfig.Builder configBuilder = new PreviewConfig.Builder().setLensFacing(CameraX.LensFacing.BACK);
         HdrPreviewExtender hdrPreviewExtender = HdrPreviewExtender.create(configBuilder);
         //拍摄预览,开启HDR,判断硬件条件是否支持开启,是则直接开启
         if(hdrPreviewExtender.isExtensionAvailable()) {
             hdrPreviewExtender.enableExtension();
         }
         preview = new Preview(configBuilder.build());
         
        //图片拍摄的配置config
        ImageCaptureConfig.Builder captureBuilder = new ImageCaptureConfig.Builder().setLensFacing(CameraX.LensFacing.BACK);
        HdrImageCaptureExtender hdrImageCaptureExtender = HdrImageCaptureExtender.create(captureBuilder);
         //拍摄照片,开启HDR,判断硬件条件是否支持开启,是则直接开启
        if(hdrImageCaptureExtender.isExtensionAvailable()) {
             hdrImageCaptureExtender.isExtensionAvailable();
         }
        imageCapture = new ImageCapture(captureBuilder.build());

总结

CameraX 是 Google 推出的一个挺不错的 JetPack 组件,入门真的非常简单,使用起来很方便,节省了很多开发时间。而且绑定了LifeCycle ,因此生命周期管理也挺省事。

虽说目前还不太成熟,但毕竟它还在测试阶段,Google未来还会修复bug和推出新功能,期待它的未来~

这篇文章只是介绍了CameraX的入门操作,想要了解更多和获取最新的信息,请前往Google家的文档。

Google的开发者文档:CameraX

免责声明:文章转载自《Android JetPack组件-CameraX初探》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Django——中间件sql 语句实现一串数字位数不足在左侧补0的技巧下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

MIPS学习笔记(一)

本章涉及MIPS变量声明、数据输入和输出、地址获取、分支跳转语句,基本上对应于任何高级语言的最基本操作。该信息的确切形式因汇编程序而异。在MIPS程序集中,标签是后跟冒号的符号名称。)syscall程序的结尾与C类似,可以调用exit函数来停止程序的执行。停止MIPS程序的一种方法是使用类似于在C中调用exit的方法。MIPS中有一个移动指令,它将一个寄存器...

浅谈 SQL 注入(注入篇)

1、 SQL注入1.1简介什么是SQL注入?它不过滤用户可以严格控制或没有限制的参数,以便用户可以将传入的参数和SQL语句组合成SQL语句,然后将其传输到web服务器。最后,它被传输到数据库以执行添加、删除、修改和查询等操作。基于此,用户可以获取数据库数据或提高其销毁数据库数据的权限。...

eeprom AT24C512 i2c总线的特点 来自eeleader的博客

今天,我花了一天时间研究i2c总线的特性。因为我想用FPGA来设计i2c总线的操作时序i2c总线是一种常用的串行总线。我想操作串行eepromAT24C512。EEPROM的容量为512KBIT,内部按照每页128字节进行组织,共512页。第一点:芯片工作速度的选择:根据AT24C512手册,芯片可以在1.8V-5.0V的电压下工作;I2C总线的最大运行速度...

WPF 制作圆角按钮

在程序对应坐置插入以下代码,或是先拖一个按钮控件到窗体中,再替换对应的代码。...

sqlite3 数据类型 批量插入

SQLite3采用动态数据类型。存储值的数据类型与值本身相关,而不是由其字段类型决定。SQLite3的动态数据类型可以向后兼容其他数据库常用的静态类型,这意味着在使用静态数据类型的数据库中使用的数据表也可以在SQLite3中使用。在SQLite2数据库中,除了声明为主键的INTEGER列外,任何列都可以存储属于任何存储类型的值。...

自定义样式滚动条

自定义IE浏览器滚动条样式追溯浏览器对滚动条的自定义,恐怕最早的就是IE浏览器了。感觉IE浏览器滚动条自定制功能并不是很强,只能控制一样显示各个部分的颜色而已,像宽度,结构等都无法控制,要靠出个性点的滚动条,很难!自定义FireFox浏览器滚动条在网上找了很多关于Firfox自定义浏览器滚动条的方法,发现firefox中却实是不支持的。...