安卓利用CameraX 拍照获这张照片的exif信息

news/2024/4/28 1:06:06/文章来源:https://blog.csdn.net/qq_41733851/article/details/136924395

一、首先导入相关权限

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-featureandroid:name="android.hardware.camera"android:required="true" /><uses-permission android:name="android.permission.CAMERA" /><!--  这个权限允许应用程序录制音频。  --><uses-permission android:name="android.permission.RECORD_AUDIO" />

二、导入依赖

// CameraX 相关依赖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'

三、Activity

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
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.core.VideoCapture;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;import com.google.common.util.concurrent.ListenableFuture;import org.json.JSONException;
import org.json.JSONObject;import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;public class MainActivity extends AppCompatActivity implements View.OnClickListener {private static final int REQUEST_CODE_RECORD_AUDIO_PERMISSION = 1001;private static final int REQUEST_CODE_CAMERA_PERMISSION = 1002;private static final int REQUEST_CODE_STORAGE_PERMISSION = 1003;private ListenableFuture<ProcessCameraProvider> processCameraProviderListenableFuture;private PreviewView previewView;private Button btn_photograph; //拍照private ImageCapture imageCapture;private CameraSelector cameraSelector;private TextView tv;private boolean isUsingFrontCamera = false; // 默认使用前置摄像头@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);previewView = findViewById(R.id.previewView);btn_photograph = findViewById(R.id.btn_photograph);tv = findViewById(R.id.tv);btn_photograph.setOnClickListener(this);// 检查权限if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED ||ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_RECORD_AUDIO_PERMISSION);} else {initializeCamera();}}// 初始化相机private void initializeCamera() {processCameraProviderListenableFuture = ProcessCameraProvider.getInstance(this);processCameraProviderListenableFuture.addListener(() -> {try {ProcessCameraProvider processCameraProvider = processCameraProviderListenableFuture.get();start(processCameraProvider);} catch (Exception e) {throw new RuntimeException(e);}}, ContextCompat.getMainExecutor(this));}@SuppressLint("RestrictedApi")private void start(ProcessCameraProvider processCameraProvider) {processCameraProvider.unbindAll();cameraSelector = new CameraSelector.Builder().requireLensFacing(isUsingFrontCamera ? CameraSelector.LENS_FACING_FRONT : CameraSelector.LENS_FACING_BACK).build();Preview preview = new Preview.Builder().build();preview.setSurfaceProvider(previewView.getSurfaceProvider());imageCapture = new ImageCapture.Builder().setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY).build();processCameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture);}@SuppressLint("RestrictedApi")@Overridepublic void onClick(View view) {if (view.getId() == R.id.btn_photograph) {captureImage();}}// 拍照private void captureImage() {long timeStamp = System.currentTimeMillis();ContentValues contentValues = new ContentValues();contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp);contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");imageCapture.takePicture(new ImageCapture.OutputFileOptions.Builder(getContentResolver(),MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues).build(),ContextCompat.getMainExecutor(this),new ImageCapture.OnImageSavedCallback() {@Overridepublic void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {Toast.makeText(MainActivity.this, "拍照保存成功", Toast.LENGTH_SHORT).show();Uri savedUri = outputFileResults.getSavedUri();if (savedUri != null) {try {InputStream inputStream = getContentResolver().openInputStream(savedUri); // 打开输入流if (inputStream != null) {ExifInterface exifInterface = new ExifInterface(inputStream); // 创建ExifInterface对象String datetime = exifInterface.getAttribute(ExifInterface.TAG_DATETIME); // 获取拍摄时间String make = exifInterface.getAttribute(ExifInterface.TAG_MAKE); // 获取相机制造商String model = exifInterface.getAttribute(ExifInterface.TAG_MODEL); // 获取相机型号String focalLength = exifInterface.getAttribute(ExifInterface.TAG_FOCAL_LENGTH); // 获取焦距String aperture = exifInterface.getAttribute(ExifInterface.TAG_APERTURE); // 获取光圈Log.d("EXIF Info", "获取拍摄时间: " + datetime);Log.d("EXIF Info", "获取相机制造商: " + make);Log.d("EXIF Info", "获取相机型号: " + model);Log.d("EXIF Info", "获取焦距: " + focalLength);Log.d("EXIF Info", " 获取光圈: " + aperture);tv.setText("获取拍摄时间: " + datetime+"\n"+"获取相机制造商: " + make+"\n"+"获取相机型号: " + model+"\n"+"获取焦距: " + focalLength+"\n"+" 获取光圈: " + aperture);inputStream.close(); // 关闭输入流}} catch (IOException e) {e.printStackTrace();}}}@Overridepublic void onError(@NonNull ImageCaptureException exception) {Toast.makeText(MainActivity.this, "拍照保存失败: " + exception.getMessage(), Toast.LENGTH_SHORT).show();}});}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_CODE_RECORD_AUDIO_PERMISSION) {for (int i = 0; i < permissions.length; i++) {if (permissions[i].equals(Manifest.permission.RECORD_AUDIO) && grantResults[i] == PackageManager.PERMISSION_GRANTED) {// 录音权限已授予if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_CAMERA_PERMISSION);} else {initializeCamera();}} else if (permissions[i].equals(Manifest.permission.RECORD_AUDIO) && grantResults[i] != PackageManager.PERMISSION_GRANTED) {Toast.makeText(this, "录音权限被拒绝", Toast.LENGTH_SHORT).show();}}} else if (requestCode == REQUEST_CODE_CAMERA_PERMISSION) {for (int i = 0; i < permissions.length; i++) {if ((permissions[i].equals(Manifest.permission.CAMERA) || permissions[i].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) &&grantResults[i] != PackageManager.PERMISSION_GRANTED) {Toast.makeText(this, "相机或存储权限被拒绝", Toast.LENGTH_SHORT).show();}}}}
}

注意:这点只是简单获取 ,想要获取更多信息,可以自行修改

四、布局代码

<?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:orientation="vertical"tools:context=".MainActivity"><androidx.camera.view.PreviewViewandroid:id="@+id/previewView"android:layout_width="match_parent"android:layout_height="200dp"/><Buttonandroid:id="@+id/btn_photograph"android:layout_width="match_parent"android:layout_height="100dp"android:text="拍照" /><TextViewandroid:id="@+id/tv"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="111"/></LinearLayout>

效果图

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

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

相关文章

2014年认证杯SPSSPRO杯数学建模B题(第一阶段)位图的处理算法全过程文档及程序

2014年认证杯SPSSPRO杯数学建模 B题 位图的处理算法 原题再现&#xff1a; 图形&#xff08;或图像&#xff09;在计算机里主要有两种存储和表示方法。矢量图是使用点、直线或多边形等基于数学方程的几何对象来描述图形&#xff0c;位图则使用像素来描述图像。一般来说&#…

Leetcode LRU---哈希➕双链表

题目链接 讲解视频 Tips&#xff1a; 代码&#xff1a; import java.util.*; // 修改导入语句&#xff0c;正确引入 java.util 包class Node{//双链表int key,value;Node pre,next;public Node(int k,int v){this.key k;this.value v;this.pre null;this.next null;}…

OpenHarmony实战开发-从0到1实现购物应用页面

概述 OpenHarmony ArkUI框架提供了丰富的动画组件和接口&#xff0c;开发者可以根据实际场景和开发需求&#xff0c;选用丰富的动画组件和接口来实现不同的动画效果。 本Codelab中&#xff0c;我们会构建一个简易的购物应用。应用包含两级页面&#xff0c;分别是主页&#xf…

【Nebula笔记】基础操作

目录 一、预备~ 二、基础操作 (一) 图空间 1. 创建图空间 2. 清空图空间 3. 其他 4. FAQ 执行DROP SPACE语句删除图空间后&#xff0c;为什么磁盘的大小没变化&#xff1f; (二) 点类型 1. 创建Tag 2. 删除Tag 3. 更新Tag 4. 其他 (三) 边类型 1. 创建Edge type…

ubuntu系统下如何使用vscode编译和调试#小白入门#

编程环境&#xff1a;ubuntu系统为18.04.1&#xff0c;vscode版本为1.66.2 一、VSCode切换中文显示&#xff1a; 1、vscode安装完成后启动,在左侧externsions中搜索“简体中文”插件&#xff0c;并完成安装&#xff1a; 2、选择右下角齿轮形状的"Manage"&#xff…

自然指数函数e^x与欧拉数e (下)

自然指数函数e^x与欧拉数e Part I: 如何找到欧拉数e 上一篇文章停在了“应该存在一个b&#xff0c;使得指数函数b^x在x0处的导数为1。且该指数函数在任意一处的导数都等于当前位置的函数值”。根据前面所知道的&#xff0c;可以用数学公式列出以下一些已知条件&#xff1a; &am…

Go语言学习Day5:函数(下)

名人说&#xff1a;莫愁千里路&#xff0c;自有到来风。 ——钱珝 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、本质、数据类型与延迟函数①函数的本质②函数的数据类型③defer延迟函数 2、匿名、回调函数与闭…

Go——map操作及原理

一.map介绍和使用 map是一种无序的基于key-value的数据结构&#xff0c;Go语言的map是引用类型&#xff0c;必须初始化才可以使用。 1. 定义 Go语言中&#xff0c;map类型语法如下&#xff1a; map[KeyType]ValueType KeyType表示键类型ValueType表示值类型 map类型的变量默认…

班级综合测评管理系统的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目持续更新中..... 2024年计算机毕业论文&#xff08;设计&#xff09;学生选题参考合集推荐收藏&#xff08;包含Springboot、jsp、ssmvue等技术项目合集&#xff09; 目录 1. …

docker 的网络管理

docker应用自带了三种类型的网络&#xff0c;然后我们自己也能自定义网络 roottest-virtual-machine:~# docker network ls NETWORK ID NAME DRIVER SCOPE 4c3e28760cff bridge bridge local afd1493dc119 host host local 5f200e2eaf22 n…

AOP切入点表达式基本格式

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 官方地址 https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/pointcuts.html AOP切入点表达式基本格式如下&#xff1a; execution(modifiers-patte…

Vscode创建php项目

1.安装中文插件&#xff08;可安装可不安装&#xff09; 2.安装主题&#xff08;可安装可不安装&#xff09; 3.安装和php相关的插件 4.打开文件夹 5.路由操作 查看项目中的route路由 浏览器中访问think 隐藏index.php入口文件 访问ThinkPHP5.1开发手册&#xff0c;复制apa…

React-1-jsx基础-事件绑定-样式处理

一.JSX基础-概念和本质 1.1 什么是JSX JSX是JavaScript和XML&#xff08;HTML&#xff09;的缩写&#xff0c;表示在JS代码中编写HTML模版结构,它是React中编写UI模版的方式 优势&#xff1a; 1. HTML的声明式模版写法 2. JS的可编程能力 JSX的本质&#xff1a; JSX并不是标…

[openGL] qt5版本+mingw编译Assimp库+调用

目录 一 版本 二 编译问题 三 CMAKE准备 四 开始编译 4.1 准备Assimp源码 4.2 编译工具准备 4.3 生成Assimp库 4.4 使用Assimp 4.4.1 准备 4.4.2 加载模型 4.4.3 模型效果 一 版本 Assimp官网上已经停止更新截至在3.3.1版本,但是这个版本编译是最稳定的,较新的版本…

WORDPRESS从WORD复制粘贴公式

整合教程&#xff1a;WordPress插件包整合教程 WordPaster支持自动上传本地图片文件&#xff0c;自动上传Word文档中的图片 步骤与效果&#xff1a; 1.打开word文档&#xff0c;复制word文档内容 2.在网页中打开编辑器页面&#xff0c;点击“粘贴本地文件,Word文档”按钮上传…

GBase8a-GDCA认证考试-复习参考题

个人能力有限&#xff0c;正确率97%&#xff08;97分&#xff09;。 请注意甄别&#xff0c;根据所学知识综合判断&#xff0c;欢迎指出错误答案。 欢迎学习天津南大通用数据技术股份有限公司|GBASE-致力于成为用户最信赖的数据库产品供应商 免费参加认证培训&#xff1a;为…

Visio中存在问题的解决方法

公式缩放 mathtype公式在visio缩放之后&#xff0c;出现了变形。 解决方法&#xff1a;每次输入公式都通过 插入->对象->mathType Equation 新建一个公式。可以避免 注&#xff1a;网上有的说在word中使用mathtype编写公式&#xff0c;之后复制到visio中。 插入波形 选择…

Java的IDEA的工程管理

模块和包的图标&#xff1a; 举个例子&#xff1a; IDEA中创建包&#xff1a; 如图所示&#xff0c;com.LBJ的意思是在com包中创建子包LBJ 参见&#xff1a; IDEA中项目、模块和包的关系_idea中模块和项目-CSDN博客

应用层协议之DNS协议

一.应用层协议的相关数据传输格式 1.文本字符串格式 应用层主要是自定义协议&#xff0c;以点外卖为例&#xff1a; 客户点开软件&#xff0c;就是应用程序和服务器之间进行网络通信交互。请求和响应可以如下设置 请求&#xff1a;用户信息&#xff0c;位置信息&#xff0c…

Vue模块化开发步骤—遇到的问题—解决办法

目录 1.npm install webpack -g 2.npm install -g vue/cli-init 3.初始化vue项目 4.启动vue项目 Vscode初建Vue时几个需要注意的问题-CSDN博客 1.npm install webpack -g 全局安装webpack 直接命令提示符运行改指令会报错&#xff0c;operation not permitted 注意&#…