【Android】使用 CameraX 实现基础录像功能

这篇具有很好参考价值的文章主要介绍了【Android】使用 CameraX 实现基础录像功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1. 基础开发环境

2. 添加相关依赖

3. APP 布局

4. 主流程逻辑

5. 调试或安装 APK

6. 项目完整代码


1. 基础开发环境

JDK:JDK17

Android Studio:Android Studio Giraffe | 2022.3.1

Android SDK:Android API 34

Gradle: gradle-8.0-bin.zip

CameraX Version: 1.1.0-alpha05

2. 添加相关依赖

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

    // *** Camera 相关依赖 ***
    def cameraxVersion = "1.1.0-alpha05";
    implementation "androidx.camera:camera-core:${cameraxVersion}"
    implementation "androidx.camera:camera-camera2:${cameraxVersion}"
    implementation "androidx.camera:camera-lifecycle:${cameraxVersion}"
 
    implementation 'androidx.camera:camera-view:1.0.0-alpha25'
    // ***********************

在 AndroidManifest.xml 文件中注册相机权限

    <!--  这个权限声明意味着此 Android 应用程序需要设备具有摄像头功能才能正常运行,
          并且如果设备没有摄像头,则应用程序将无法在该设备上安装或运行。
          "android:required = "true"" 表示摄像头功能是必需的,而不是可选的。 -->
    <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />
    <!--  注册相机权限  -->
    <!--  这个权限允许应用程序读取摄像头的输入并拍照或录制视频。如果没有这个权限,应用程序将无法访问设备的相机功能。  -->
    <uses-permission android:name="android.permission.CAMERA" />
    <!--  这个权限允许应用程序录制音频。  -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <!--  这个权限允许应用程序向外部存储(例如SD卡)写入数据。而这个权限只适用于 Android 版本号不大于 28 的设备。  -->
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />

3. APP 布局

使用 LinearLayout 布局,其中添加一个 PreviewView 用来显示相机画面的预览,添加一个 Button 用来控制录像开始和结束。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="@color/black"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">
 
    <androidx.camera.view.PreviewView
        android:id="@+id/previewView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="3" />
 
    <Button
        android:id="@+id/captureButton"
        android:layout_width="wrap_content"
        android:layout_height="100dp"
        android:layout_weight="1"
        android:text="@string/capture_button" />
 
</LinearLayout>
<resources>
    <string name="app_name">camera-video-capture</string>
    <string name="capture_button">录像</string>
</resources>

4. 主流程逻辑

package com.example.capture;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Preview;
import androidx.camera.core.VideoCapture;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.concurrent.ExecutionException;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ListenableFuture<ProcessCameraProvider> processCameraProviderListenableFuture;
    PreviewView previewView;
    Button captureButton;
    private VideoCapture videoCapture;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // onCreate 在活动被创建时被调用的。
        // 它的作用是对活动进行初始化,例如加载布局文件,设置事件监听器和初始化变量等。
        // `Bundle savedInstanceState` 参数用于保存活动状态,以便在活动被销毁后能够恢复它的状态。
        super.onCreate(savedInstanceState);
        // 将指定的布局文件加载到当前 Activity 中并显示在屏幕上。
        setContentView(R.layout.activity_main);

        // 从当前布局中查找具有指定 ID 的视图,并将其返回为 Java 对象。
        previewView = findViewById(R.id.previewView);
        captureButton = findViewById(R.id.captureButton);

        // 将当前类实现的 OnClickListener 接口设置为 captureButton 的点击事件监听器,
        // 以便在单击 captureButton 时调用类中的 onClick() 方法来处理点击事件。
        captureButton.setOnClickListener(this);

        // 这行代码的作用是获取相机提供者的实例,它是使用 Android CameraX API 实现相机功能的关键对象之一,
        // 通过它可以获取相机设备、预览用例、图像分析用例等等,从而实现相机应用的各种功能。
        // 此代码返回一个ListenableFuture对象,用于异步获取相机提供者的实例。
        processCameraProviderListenableFuture = ProcessCameraProvider.getInstance(this);
        // 监听摄像头的准备情况。准备好时,该代码块中的 start() 方法将被调用,以便启动相机。
        processCameraProviderListenableFuture.addListener(() -> {
            try {
                ProcessCameraProvider processCameraProvider = processCameraProviderListenableFuture.get();
                start(processCameraProvider);
            } catch (ExecutionException | InterruptedException e) {
                throw new RuntimeException(e);
            }
            // 将监听器绑定到主线程,以确保在 UI 上下文中运行该代码块。
        }, ContextCompat.getMainExecutor(this));

    }

    @SuppressLint("RestrictedApi")
    private void start(ProcessCameraProvider processCameraProvider) {
        // 取消当前已经绑定的摄像头设备,释放它们的资源,以便其他应用或者进程可以使用这些摄像头设备。
        // 这个方法通常在摄像头应用程序退出或者暂停时调用,以确保摄像头设备不会一直占用系统资源。
        processCameraProvider.unbindAll();

        // 创建一个相机选择器对象,并指定选择前置摄像头。
        CameraSelector cameraSelector = new CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
                .build();

        // 创建一个相机预览对象
        // 并将其与一个 SurfaceView 组件(previewView)的 SurfaceProvider 绑定,从而在该组件上显示相机预览画面。
        Preview preview = new Preview.Builder().build();
        preview.setSurfaceProvider(previewView.getSurfaceProvider());

        // 创建一个视频捕捉对象
        // 设置视频帧率为 30 帧/秒。这可以确保捕捉到的视频画面流畅,避免出现卡顿和不连贯的情况。
        videoCapture = new VideoCapture.Builder()
                .setVideoFrameRate(30)
                .build();

        // 在 Android 设备上启动相机,并将其与当前生命周期绑定,以便在应用程序暂停或停止时释放相机资源。
        // 该方法接受一个 `CameraSelector` 对象用于选择相机设备,一个 `Preview` 对象用于显示预览,以及一个 `videoCapture` 对象用于捕获视频。
        processCameraProvider.bindToLifecycle(this, cameraSelector, preview, videoCapture);
    }

    @SuppressLint("RestrictedApi")
    @Override
    public void onClick(View view) {
        // onClick(View view) 的作用是为按钮或其他视图设置点击事件处理程序。
        // 当用户点击该视图时,该方法会被调用并执行其中的代码。
        if (view.getId() == R.id.captureButton) {
            if (captureButton.getText() == "录像") {
                captureButton.setText("停止");
                captureVideo();
            } else {
                captureButton.setText("录像");
                videoCapture.stopRecording();
            }
        }
    }

    @SuppressLint("RestrictedApi")
    private void captureVideo() {
        if (videoCapture != null) {
            long timeStamp = System.currentTimeMillis();
            // 通过 ContentValues 对象设置文件名和文件类型
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp);
            contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");

            if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return;
            }
            videoCapture.startRecording(
                    // 第一个参数 OutputFileOptions 用于指定视频文件的输出位置和其他选项。
                    new VideoCapture.OutputFileOptions.Builder(
                            getContentResolver(),
                            MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                            contentValues
                    ).build(),
                    // 第二个参数 Executor 指定用于指定视频录制的线程。
                    ContextCompat.getMainExecutor(this),
                    // 第三个参数 OnImageSavedCallback 用于在视频录制完成或出错时进行回调。
                    new VideoCapture.OnVideoSavedCallback() {
                        @Override
                        public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) {
                            Toast.makeText(MainActivity.this, "Saving...", Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
                            Toast.makeText(MainActivity.this, "Error: " + message, Toast.LENGTH_SHORT).show();
                        }
                    }

            );

        }
    }
}

5. 调试或安装 APK

使用 USB 调试或者 Build 出 APK(Build -> Make Project)然后找到 app-debug.apk 文件进行安装。

注意:由于代码逻辑中没有权限申请部分,需要在安装好后手动开启拍照权限。

已经编译好的 APK 文件见文章开头,可直接下载安装。文章来源地址https://www.toymoban.com/news/detail-630316.html

6. 项目完整代码

https://gitee.com/hl0929/camera-video-capture

到了这里,关于【Android】使用 CameraX 实现基础录像功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android笔记(八):基于CameraX库结合Compose和传统视图组件PreviewView实现照相机画面预览和照相功能

    CameraX是JetPack库之一,通过CameraX可以向应用增加相机的功能。在下列内容中,将介绍一个结合CameraX实现一个简单的拍照应用。本应用必须采用Android SDK 34。并通过该简单示例,了解传统View层次组件的UI组件如何与Compose组件结合实现移动应用界面的定制。 首先,新建一个项目

    2024年02月08日
    浏览(42)
  • Android 实现相机(CameraX)预览

    CameraX 是一个 Jetpack 库,旨在帮助您更轻松地开发相机应用。 对于新应用,我们建议从 CameraX 开始。它提供一致且易于使用的 API,适用于绝大多数 Android 设备,并向后兼容 Android 5.0(API 级别 21)。 CameraX 支持大多数常见的相机用例: 预览 :在屏幕上查看图片。 图片分析 :

    2024年02月15日
    浏览(41)
  • Android 使用Camera1实现相机预览、拍照、录像

    本文介绍如何从零开始,在 Android 中实现 Camera1 的接入,并在文末提供 Camera1Manager 工具类,可以用于快速接入 Camera1 。 Android Camera1 API 虽然已经被 Google 废弃,但有些场景下不得不使用。 并且 Camera1 返回的帧数据是 NV21 ,不像 Camera2 、 CameraX 那样,需要自己再转一层,才能得

    2024年02月08日
    浏览(44)
  • Android Camera开发入门(3):CameraX的使用

    CameraX API简介 在前两篇博客中,我们介绍了Camera基础知识和Camera2 API的使用。为了进一步简化相机应用开发,Google推出了CameraX API,它提供了一个更加简洁、易于使用的接口,帮助开发者快速实现高质量的相机功能。本篇博客将带领你了解CameraX的使用方法,并提供相应的示例

    2024年02月11日
    浏览(37)
  • Android Studio开发之路(七)CameraX&&Opencv的使用

    工作目标:做一个显示单通道图像的相机,实现预览和拍照。 原本是调用opencv-android里边的JavaCamera2View来实现,这个用起来比较方便,它提供了集成好的相机预览界面,并且提供了帧处理函数。但是问题是用opencv相机获取到的帧图片分辨率不高,达不到目标效果。 而CameraX作

    2024年01月21日
    浏览(47)
  • 使用 CameraX 在 Jetpack Compose 中构建相机 Android 应用程序

    CameraX 是一个 Jetpack 库,旨在帮助简化相机应用程序的开发。 [camerax官方文档] https://developer.android.com/training/camerax CameraX的几个用例: Image Capture Video Capture Preview Image analyze 具体如何使用相关用例,请查看上面的官方链接。 下面仅就视频录制用例来叙述相关实现流程。 添加

    2024年02月06日
    浏览(65)
  • android camera系列(Camera1、Camera2、CameraX)的使用以及输出的图像格式

    1.1.1、布局 1.1.2、实现预览 Camera.open() 打开摄像头 setPreviewDisplay 设置预览展示的控件 startPreview 开始预览 发现预览是横着的,需要使用 setDisplayOrientation 调整预览图像的方向 1.1.3、获取摄像头的原始数据 setPreviewCallback 设置预览数据的回调 2560*1440 默认返回图像的分辨率 Image

    2024年02月21日
    浏览(51)
  • Android CameraX适配Android13的踩坑之路

    最近把AGP插件升级到8.1.0,新建项目的时候目标版本和编译版本都是33,发现之前的demo使用Camerax拍照和录像都失败了,于是查看了一下官网和各种资料,找到了Android13的适配方案. 与早期版本一样,Android 13 包含一些行为变更,这些变更可能会影响您的应用。以下行为变更仅影

    2024年02月12日
    浏览(74)
  • Android相机调用-CameraX【外接摄像头】【USB摄像头】

    Android相机调用有原生的Camera和Camera2,我觉得调用代码都太复杂了,CameraX调用代码简洁很多。 说明文档:https://developer.android.com/jetpack/androidx/releases/camera?hl=zh-cn 现有查到的调用资料都不够新,对于外接摄像头(USB摄像头)这类非前置也非后置摄像头的设备调用,都说是没有实

    2024年02月09日
    浏览(52)
  • Android中使用原生MediaRecorder APi实现录音功能

    一、MediaRecorder简介 MediaRecorder是Android中的一个API,可以用来实现录音功能。它继承自android.media.MediaRecorder类,可以实现音频和视频的录制。 二、MediaRecorder的使用 1、首先,实例化一个MediaRecorder对象,并设置音频源: 2、设置音频的输出格式: 3、设置音频的编码格式: 4、设

    2024年02月09日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包