Android CameraX实现摄像头预览、拍照、录制视频

Android CameraX实现摄像头预览、拍照、录制视频,第1张

概述一、前言从Camera1到Camera2,再到现在的Jetpack中的CameraX,Google一直在致力于让Android应用开发者更加方便的去使用摄像头相关的API,更加简单快速的实现摄像头相关的应用功能;下面就来学习一下使用CameraX实现拍照和录制视频功能;二、CameraX概述CameraX是AndroidJetpack

一、前言

从Camera1到Camera2,再到现在的Jetpack中的CameraX,Google一直在致力于让AndroID应用开发者更加方便的去使用摄像头相关的API,更加简单快速的实现摄像头相关的应用功能;下面就来学习一下使用CameraX实现拍照和录制视频功能;

二、CameraX概述

CameraX是AndroID Jetpack中的组件,旨在简化相机相关的应用开发工作,但是要注意的是CameraX向下最低兼容到AndroID 5.0(API 21);CameraX利用了Camera2的功能,但采取了一种具有生命周期感知能力且基于用例(UseCase)的更简单的方式,它还解决了设备兼容性问题。

三、CameraX使用

添加依赖:

在Module的build.gradle中添加CameraX相关的依赖

dependencIEs {    .....    def camerax_version = "1.0.0-beta07"    // CameraX core library using camera2 implementation    implementation "androIDx.camera:camera-camera2:$camerax_version"    // CameraX lifecycle library    implementation "androIDx.camera:camera-lifecycle:$camerax_version"    // CameraX VIEw class    implementation "androIDx.camera:camera-vIEw:1.0.0-Alpha14"}

同时CameraX需要一些属于java8的方法,因此我们需要相应地设置编译选项。在build.gradle文件中androID块的末尾,buildTypes之后,添加以下内容:

androID {  ... compileOptions {        sourceCompatibility JavaVersion.VERSION_1_8        targetCompatibility JavaVersion.VERSION_1_8    }  }

添加相关权限

添加相机权限,这里因为我们还要实现照片拍摄,视频录制所以除了相机权限,还需要录音权限,以及存储的读写权限;

     <uses-feature androID:name="androID.harDWare.camera.any" />    <uses-permission androID:name="androID.permission.RECORD_AUdio" />    <uses-permission androID:name="androID.permission.CAMERA" />    <uses-permission androID:name="androID.permission.READ_EXTERNAL_STORAGE"/>    <uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE"/>

相机预览

相机预览我们肯定是要有一个显示摄像头画面的VIEw,在使用Camera1或Camera2时我们一般都是使用SurfaceVIEw来显示摄像头画面,CameraX中提供PrevIEwVIEw
作为显示摄像头画面的VIEw

所以我么在布局中添加一个PrevIEwVIEw

<FrameLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent">    <androIDx.camera.vIEw.PrevIEwVIEw        androID:ID="@+ID/prevIEw_activity_vIDeo_recode"        androID:layout_wIDth="match_parent"        androID:layout_height="match_parent" /></FrameLayout>

并且使用PrevIEw相关的API实现摄像头画面的预览

    @Suppresslint("RestrictedAPI")    private voID prevIEw() {        ListenableFuture<ProcessCameraProvIDer> ListenableFuture = ProcessCameraProvIDer.getInstance(mActivity);        try {            mProcessCameraProvIDer = ListenableFuture.get();            mProcessCameraProvIDer = ListenableFuture.get();            mPrevIEw = new PrevIEw.Builder()                    .setTargetResolution(new Size(640, 480))                    .build();            mPrevIEw.setSurfaceProvIDer(mPrevIEwVIEw.createSurfaceProvIDer());            ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()                    .build();            imageAnalysis                    .setAnalyzer(ContextCompat.getMainExecutor(mActivity),                            new ImageAnalysis.Analyzer() {                                @OverrIDe                                public voID analyze(@NonNull ImageProxy image) {                                    Log.e(TAG, "analyze: " + image);                                    image.close();                                }                            }                    );            mProcessCameraProvIDer.bindTolifecycle((lifecycleOwner) mActivity, CameraSelector.DEFAulT_BACK_CAMERA,                    mPrevIEw,                    imageAnalysis            );        } catch (Exception e) {            e.printstacktrace();        }    }

我们这里在实现摄像头画面预览的同时,还添加了一ImageAnalysis 图像分析用例,ImageAnalysis设置一个ImageAnalysis.Analyzer分析器,这个用例是用来实现每一帧画面的数据分析的,每一帧画面都会回调到analyze(ImageProxy image)方法
我们可以从IamgeProxy中拿到每一帧画面的图像数据;

这里要注意在回调方法中使用完IamgeProxy后,一定要调用IamgeProxy.close()方法关闭,否则analyze(ImageProxy image)这个方法只会回调一次,这是个坑一定要注意关闭;

拍摄照片

使用IamgeCapture相关的API实现照片拍摄功能

 private voID takePhoto() {        ImageCapture imageCapture = new ImageCapture.Builder()                //优化捕获速度,可能降低图片质量                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)                //设置宽高比                .setTargetResolution(new Size(640, 480))                //设置初始的旋转角度                .build();        String dirPath = getExternalfilesDir("").getabsolutePath()                + file.separator + "TestRecode";        file dirfile = new file(dirPath);        if (!dirfile.exists()) {            boolean mkdir = dirfile.mkdir();            Log.e(TAG, "takePhoto: mkdir:" + mkdir);        }        file file = new file(dirfile, System.currentTimeMillis() + ".jpg");        if (!file.exists()) {            try {                boolean newfile = file.createNewfile();                Log.e(TAG, "takePhoto: newfile:" + newfile);            } catch (IOException e) {                e.printstacktrace();            }        }        ImageCapture.OutputfileOptions outputfileOptions = new ImageCapture.OutputfileOptions.Builder(file).build();        mProcessCameraProvIDer.bindTolifecycle((lifecycleOwner) mActivity, CameraSelector.DEFAulT_BACK_CAMERA,                imageCapture        );        imageCapture.takePicture(outputfileOptions, ContextCompat.getMainExecutor(mActivity), new ImageCapture.OnImageSavedCallback() {            @OverrIDe            public voID onImageSaved(@NonNull ImageCapture.OutputfileResults outputfileResults) {                Log.e(TAG, "onImageSaved: " + outputfileResults);                Uri savedUri = outputfileResults.getSavedUri();                Log.e(TAG, "onImageSaved: " + savedUri);                if (savedUri == null) {                    savedUri = Uri.fromfile(file);                }                Toast.makeText(mActivity, "拍摄成功", Toast.LENGTH_SHORT).show();            }            @OverrIDe            public voID one rror(@NonNull ImageCaptureException exception) {                Log.e(TAG, "onError: " + exception);            }        });    }

录制视频

使用VIDeoCapture相关的API实现视频录制的功能

  @Suppresslint("RestrictedAPI")    private voID startRecorder() {        mVIDeoCapture = new VIDeoCapture.Builder()                .build();        String dirPath = getExternalfilesDir("").getabsolutePath()                + file.separator + "TestRecode";        file dirfile = new file(dirPath);        if (!dirfile.exists()) {            boolean mkdir = dirfile.mkdir();            Log.e(TAG, "startRecorder: mkdir:" + mkdir);        }        file file = new file(dirfile, System.currentTimeMillis() + ".mp4");        if (!file.exists()) {            try {                boolean newfile = file.createNewfile();                Log.e(TAG, "startRecorder: newfile:" + newfile);            } catch (IOException e) {                e.printstacktrace();            }        }        mProcessCameraProvIDer.bindTolifecycle(                this, CameraSelector.DEFAulT_BACK_CAMERA, mPrevIEw,                mVIDeoCapture);        mVIDeoCapture.startRecording(file, ContextCompat.getMainExecutor(mActivity),                new VIDeoCapture.OnVIDeoSavedCallback() {                    @OverrIDe                    public voID onVIDeoSaved(@NonNull file file) {                        Log.e(TAG, "onVIDeoSaved: " + file);                        Toast.makeText(mActivity, "录制结束", Toast.LENGTH_SHORT).show();                    }                    @OverrIDe                    public voID one rror(int vIDeoCaptureError, @NonNull String message, @Nullable Throwable cause) {                        Log.e(TAG, "onError: " + vIDeoCaptureError + "," + message);                        Toast.makeText(mActivity, "录制出错:code:" + vIDeoCaptureError + "," + message, Toast.LENGTH_SHORT).show();                        mIsRecording = false;                    }                }        );    }    @Suppresslint("RestrictedAPI")    private voID stopRecorder() {        if (mVIDeoCapture != null) {            mVIDeoCapture.stopRecording();        }    }

一开始的时候回调到onError中,vIDeoCaptureError是2,message是Mediamuxer creation Failed!,百度也没有找到解决方法,后来发现是视频文件file没有创建成功,所以要注意检查视频文件file有没有创建成功;

当然别忘记了在程序中先要动态申请相关权限;

以上就是使用CameraX实现摄像头预览、拍照、视频录制功能;

Demo源码地址:https://github.com/maqing-programmer/CameraXDemo

总结

以上是内存溢出为你收集整理的Android CameraX实现摄像头预览、拍照、录制视频全部内容,希望文章能够帮你解决Android CameraX实现摄像头预览、拍照、录制视频所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1024506.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存