美文网首页UIandroid
Android 音视频开发(四) -- CameraX 实现预览

Android 音视频开发(四) -- CameraX 实现预览

作者: 夏至的稻穗 | 来源:发表于2020-07-13 20:09 被阅读0次

    音视频学习demo,正在升级打怪,加油鸭~
    Android 音视频开发(一) -- 使用AudioRecord 录制PCM(录音);AudioTrack播放音频
    Android 音视频开发(二) -- Camera1 实现预览、拍照功能
    Android 音视频开发(三) -- Camera2 实现预览、拍照功能
    工程:https://github.com/LillteZheng/VideoDemo

    一. Camerax 简介

    在前面两章中,我们已经学习了 Camera1 Android 音视频开发(二) -- Camera1 实现预览、拍照功能 和 Camera2 Android 音视频开发(三) -- Camera2 实现预览、拍照功能,但从上面两章可以看出来,API 的调用还是比较繁琐的,而且像一些最佳尺寸,角度等还得自己算,从 Camera2 的开发流程就可以知道:

    在这里插入图片描述
    真的很难记住这些流程;google 也意识到这个问题,所以推出了 Camerax ,它虽然底层也是利用了 Camera2 的功能,但它的使用却更加简洁,它的主要优势如下:
    1. 更加简洁的 API 调用,基本十几行代码就能实现预览
    2. Camerax 为 Jetpack 的支持库,所以也具备感知生命周期的功能,即你无需自己释放 生命周期
    3. 更好兼容性
    4. 更多功能,比如图片分析等

    注意,Camerax 也只支持 API21 及以上,本次效果如下:

    GIF.gif

    二. Camerax 使用说明

    Camerax 的使用非常简单,首先,添加关联库

    def camerax_version = "1.0.0-beta06"
    // CameraX 核心库
    implementation "androidx.camera:camera-camera2:$camerax_version"
    // CameraX 生命周期
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
    // CameraX view 集合,比如 cameraview,preview等
    implementation "androidx.camera:camera-view:1.0.0-alpha10"
    

    权限

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

    2.1 预览

    首先,先通过

      ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
    

    返回当前可以绑定生命周期的 ProcessCameraProvider,ProcessCameraProvider 它会和宿主绑定生命周期,这样就不用担心打开相机和关闭的问题了。

    接着,向 cameraProviderFuture 注册一个监听,第一个参数是一个 runnable,第二个参数是线程池,即runnable 运行在哪个线程中:

    cameraProviderFuture.addListener(Runnable {}, ContextCompat.getMainExecutor(this))
    

    上面我们让它运行在主线程的线程池中,这样,在这个 runnable 中,就可以配置我们的 capture 了:

            //创建相机进程监听
            ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
            cameraProviderFuture.addListener(new Runnable() {
                @SuppressLint("RestrictedApi")
                @Override
                public void run() {
                    try {
                        //将相机的生命周期和activity的生命周期绑定,camerax 会自己释放,不用担心了
                        ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                        //预览的 capture,它里面支持角度换算
                        Preview preview = new Preview.Builder().build();
    
                        //创建图片的 capture
                        mImageCapture = new ImageCapture.Builder()
                                .setFlashMode(ImageCapture.FLASH_MODE_AUTO)
                                .build();
    
                       
                        //选择后置摄像头
                        CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
    
                        //预览之前先解绑
                        cameraProvider.unbindAll();
    
                        //将数据绑定到相机的生命周期中
                        Camera camera = cameraProvider.bindToLifecycle(CameraxActivity.this, cameraSelector, preview, mImageCapture);
                        //将previewview 的 surface 给相机预览
                        preview.setSurfaceProvider(mViewFinder.createSurfaceProvider(camera.getCameraInfo()));
    
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            },ContextCompat.getMainExecutor(this));
    

    可以看到,使用 ProcessCameraProvider.getInstance(this) 获取当前的 ProcessCameraProvider 去监听宿主的生命周期。

    创建并确认 CameraProvider 后,执行步骤如下

    1. 创建 Preview,使用 new Preview.Builder().build() 创建Preview,它是相机预览的数据流,图像数据会通过它来输出,比如输出到 Surface 中
    2. 创建 ImageCapture 用于拍照,这里的 builder 都可以设置参数,比如大小,曝光等
    3. 指定所需的相机 LensFacing 选项,这里直接使用后置即可
    4. 将所选相机和任意用例绑定到生命周期,通过 cameraProvider.bindToLifecycle,将宿主的生命周期,与 cameraSelector,preview和mImageCapture判定起来。
    5. 将 Preview 连接到 PreviewView,preview.setSurfaceProvider() 设置要预览的 surface

    上面的的 mViewFinder 其实是一个 PreviewView ,这是一种可以剪裁、缩放和旋转以确保正确显示的 View,即不用你自己去设置预览的角度等问题了。

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

    2.2. 拍照

    上面已经设置了 mImageCapture,拍照呢,在 Camerax 中也很简单,使用 takePicture 即可,如下

     public void takePhoto(View view) {
            if (mImageCapture != null) {
                File dir = new File(Constants.PATH);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                //创建文件
                File file = new File(Constants.PATH,"testx.jpg");
                if (file.exists()) {
                    file.delete();
                }
                //创建包文件的数据,比如创建文件
                ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build();
    
                //开始拍照
                mImageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(this), new ImageCapture.OnImageSavedCallback() {
                    @Override
                    public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                    //    Uri savedUri = outputFileResults.getSavedUri();
                        Toast.makeText(CameraxActivity.this, "保存成功: ", Toast.LENGTH_SHORT).show();
                    }
    
                    @Override
                    public void onError(@NonNull ImageCaptureException exception) {
                        Toast.makeText(CameraxActivity.this, "保存失败", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }
    

    注释已经很清楚了,注意我们可以使用 ImageCapture.OutputFileOptions 让 Camerax 去帮我们保存图片文件。

    参考:
    https://codelabs.developers.google.com/codelabs/camerax-getting-started/#0

    相关文章

      网友评论

        本文标题:Android 音视频开发(四) -- CameraX 实现预览

        本文链接:https://www.haomeiwen.com/subject/aupzcktx.html