Google JetPack组件-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:id="@+id/containerCamera"

            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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容