【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-7.2-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-featureandroid: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-permissionandroid: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.PreviewViewandroid:id="@+id/previewView"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="3" /><Buttonandroid: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-image-capture</string><string name="capture_button">拍照</string>
</resources>

4. 主流程逻辑

package com.example.capture;import android.content.ContentValues;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.content.ContextCompat;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 ImageCapture imageCapture;@Overrideprotected 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));}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());// 创建一个 ImageCapture 对象,用于拍摄照片。// 设置拍照模式为最小化延迟模式,这意味着拍照时将尽可能快地捕获图像。imageCapture = new ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY).build();// 在 Android 设备上启动相机,并将其与当前生命周期绑定,以便在应用程序暂停或停止时释放相机资源。// 该方法接受一个 `CameraSelector` 对象用于选择相机设备,一个 `Preview` 对象用于显示预览,以及一个 `ImageCapture` 对象用于捕获图像。processCameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);}@Overridepublic void onClick(View view) {// onClick(View view) 的作用是为按钮或其他视图设置点击事件处理程序。// 当用户点击该视图时,该方法会被调用并执行其中的代码。if (view.getId() == R.id.captureButton) {captureImage();}}private void captureImage() {long timeStamp = System.currentTimeMillis();// 通过 ContentValues 对象设置文件名和文件类型ContentValues contentValues = new ContentValues();contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp);contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");imageCapture.takePicture(// 第一个参数 OutputFileOptions 指定了照片保存的位置和格式等信息。new ImageCapture.OutputFileOptions.Builder(getContentResolver(),MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues).build(),// 第二个参数 Executor 指定了保存照片时要运行的线程。ContextCompat.getMainExecutor(this),// 第三个参数 OnImageSavedCallback 指定了保存照片完成后的回调函数,可以在其中进行一些提示或其他操作。new ImageCapture.OnImageSavedCallback() {@Overridepublic void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {Toast.makeText(MainActivity.this, "Saving...", Toast.LENGTH_SHORT).show();}@Overridepublic void onError(@NonNull ImageCaptureException exception) {Toast.makeText(MainActivity.this, "Error: " + exception.getMessage(), Toast.LENGTH_SHORT).show();}});}
}

5. 调试或安装 APK

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

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

已经编译好的 APK 文件见文章开头,可直接下载安装。

6. 项目完整代码

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/20188.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端如何并发控制

本文节选自我的博客&#xff1a;前端如何并发控制 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是MilesChen&#xff0c;偏前端的全栈开发者。&#x1f4dd; CSDN主页&#xff1a;爱吃糖的猫&#x1f525;&#x1f4e3; 我的博客&#xff1a;爱吃糖的猫&#x1f4d…

2023年人工智能技术与智慧城市发展白皮书

人工智能与智慧城市是当前热门的话题和概念&#xff0c;通过将人工智能技术应用在城市管理和服务中&#xff0c;利用自动化、智能化和数据化的方式提高城市运行效率和人民生活质量&#xff0c;最终实现城市发展的智慧化&#xff0c;提升城市居民的幸福感。 AI技术在城市中的应…

QT中使用ffmpeg的api进行视频的播放

在了解ffmpeg使用api进行视频的播放之前&#xff0c;我们首先了解一下视频的播放流程。 一、视频的播放流程 首先是我们最常见的视频文件&#xff0c;在播放流程中首先是要打开视频文件&#xff0c;将视频文件中的数据进行解封装&#xff0c;之后再将解封装之后的视频进行解码…

【C#学习笔记】引用类型(2)

文章目录 ObjectEqualsGetTypeToStringGetHashCode string逐字文本复合格式字符串字符串内插 StringBuilderStringBuilder 的工作原理StringBuilder提供的方法访问字符迭代字符查询字符 dynamic Object 支持 .NET 类层次结构中的所有类&#xff0c;并为派生类提供低级别服务。…

【docker】docker镜像原理

目录 一、操作系统组成部分二、Linux文件系统三、docker镜像原理四、说明五、镜像制作5.1 方式一&#xff1a;容器转镜像5.2 方式二&#xff1a;dockerfile5.2.1 dockerfile说明5.2.2 dockerfile关键字 一、操作系统组成部分 1.进程调度子系统 2.进程通信子系统 3.内存管理子系…

Python实现GA遗传算法优化循环神经网络分类模型(LSTM分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;最早是由美国的 John holland于20世…

实战 02|「可点击图片」

前言 实践是最好的学习方式&#xff0c;技术也如此。 文章目录 前言一、功能需求&#xff08;一&#xff09;1、功能需求描述 一、功能需求&#xff08;一&#xff09; 1、功能需求描述 用户可以点击图片来执行相应的操作&#xff08;显示 Toast 信息&#xff09;&#xff1b;…

全面解析大语言模型的工作原理

当ChatGPT在去年秋天推出时&#xff0c;在科技行业乃至世界范围内引起了轰动。当时&#xff0c;机器学习研究人员尝试研发了多年的语言大模型&#xff08;LLM&#xff09;&#xff0c;但普通大众并未十分关注&#xff0c;也没有意识到它们变得多强大。 如今&#xff0c;几乎每个…

无代码开发(BIP旗舰版-YonBuilder)

目录 我的应用 新建领域 菜单管理 应用构建 新建应用 对象建模 新增业务对象 新增业务实体 页面建模 新增页面 编辑页面 发布管理 我的应用 角色管理 yonbuilder开发平台&#xff0c;提供标准服务和专业开发服务&#xff1b; 本篇文章只演示标准服务的可视化应用…

new一个构造函数

new 一个构造函数发生了什么&#xff1f; new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。 new 关键字会进行如下的操作&#xff1a; 1.创建一个空的简单 JavaScript 对象&#xff0c;即{}&#xff1b; 2.链接该对象到另一个对象(即设置该对象…

Flink State 和 Fault Tolerance详解

有状态操作或者操作算子在处理DataStream的元素或者事件的时候需要存储计算的中间状态&#xff0c;这就使得状态在整个Flink的精细化计算中有着非常重要的地位&#xff1a; 记录数据从某一个过去时间点到当前时间的状态信息。以每分钟/小时/天汇总事件时&#xff0c;状态将保留…

【C++】基础练习(一)||从C到C++函数

C基础练习&#xff08;一&#xff09; 从C 到C函数 从C 到C ⭐️C是在C语言基础山改进发展而来的&#xff0c;是C语言的一个超集。 1.关于C语言和C的关系&#xff0c;以下说法正确的是&#xff1a;A A.C兼容C语言 B.C语言部分兼容C C.C部分兼容C语言 D.C语言兼容C 分析&#x…

调整图片中的人物头像的位置(裁剪图片的时候)

其实调整图片的适应边框的属性 我们首先会想到 object-fit object-fit CSS 属性指定可替换元素&#xff08;例如&#xff1a; 或 &#xff09;的内容应该如何适应到其使用高度和宽度确定的框。 contain 被替换的内容将被缩放&#xff0c;以在填充元素的内容框时保持其宽高比…

弹性布局,网格布局,JavaScript

弹性盒子布局&#xff08;Flexbox Layout&#xff09;&#xff1a;通过display: flex;设置容器为弹性盒子&#xff0c;可以实现更复杂的自适应和响应式布局。 网格布局&#xff08;Grid Layout&#xff09;&#xff1a;通过display: grid;设置容器为网格布局&#xff0c;可以将…

Unity 引擎做残影效果——2、屏幕后处理方式

Unity实现残影效果 大家好&#xff0c;我是阿赵。 这里继续介绍Unity里面做残影的方法。之前介绍了BakeMesh的方法做残影&#xff0c;这一期介绍的是用屏幕后处理的方法做残影。 一、原理 之前的BakeMesh方法&#xff0c;是真的生成了很多个网格模型在场景里面。如果用后处理做…

day49-Springboot

Springboot 1. Springboot简介 1.1 简介&#xff1a;Springboot来简化Spring应用开发的一个框架&#xff0c;约定大于配置 1.2 优点&#xff1a; 可以快速的构建独立运行的Spring项目&#xff1b; 框架内有Servlet容器&#xff0c;无需依赖外部&#xff0c;所以不需要达成w…

正则匹配img标签里面src

正则&#xff1a; (?<src\s*\s*\")\S(?\"{1})匹配效果&#xff1a;

Ansible —— playbook 剧本

Ansible —— playbook 剧本 一、playbook的概述1.playbook简介2.什么是Ansible playbook剧本&#xff1f;3.Ansible playbook剧本的特点4.如何使用Ansible playbook剧本&#xff1f;5.playbooks 本身由以下各部分组成 二、playbook示例1.运行playbook2.定义、引用变量3.指定远…

HarmonyOS/OpenHarmony元服务开发-卡片使用动效能力

ArkTS卡片开放了使用动画效果的能力&#xff0c;支持显式动画、属性动画、组件内转场能力。需要注意的是&#xff0c;ArkTS卡片使用动画效果时具有以下限制&#xff1a; 以下示例代码实现了按钮旋转的动画效果&#xff1a; Entry Component struct AttrAnimationExample { St…

Vue axios + Vue使用

相对于原生的阿贾克斯&#xff0c;axios提供的方法使用起来会更加的简便&#xff0c;之前网络数据获取到了&#xff0c;如何和vue一起使用呢&#xff1f; 网络应用的核心就是data中的数据一部分是通过网络获取到的。所以在方法当中发起网络请求&#xff0c;在响应回来之后将服…