使用摄像头预览和拍照(Camera1)

2024-08-21 16:38

本文主要是介绍使用摄像头预览和拍照(Camera1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考文章:
https://blog.csdn.net/u011418943/article/details/107256406
https://blog.csdn.net/xiaodongvtion/article/details/110951754

Camera1的类android.hardware.Camera。Camera类常用的方法:

方法

描述

getParameters()

获取摄像头参数

setParameters()

设置摄像头参数

setPreviewDisplay()

为摄像头指定一个显示预览画面的SurfaceView

open()

打开摄像头

startPreview()

开始预览

stopPreview()

停止预览

release()

释放摄像头资源

takePicture()

进行拍照

1 代码

CameraPreview:

GitHub - hanyuhang-hz/android-demos

MainActivity.java

public class MainActivity extends Activity {public final static String TAG = "CameraPreview";private Camera camera;private boolean isPreview = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.CAMERA}, 1);}if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){ActivityCompat.requestPermissions(MainActivity.this, new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);}// 设置全屏显示getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 判断手机是否安装SD卡if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {Toast.makeText(this, "请安装SD卡!", Toast.LENGTH_SHORT).show();}SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);final SurfaceHolder surfaceHolder = surfaceView.getHolder();// 设置该SurfaceHolder自己不维护缓冲surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);ImageButton preview = (ImageButton) findViewById(R.id.preview);preview.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 如果相机为非预览模式,则打开相机if (!isPreview) {camera = Camera.open();isPreview = true;}try {// 设置用于显示预览的SurfaceViewcamera.setPreviewDisplay(surfaceHolder);Camera.Parameters parameters = camera.getParameters();// 测试Camera.Parameters// (1)setPictureFormat======================================// PixelFormat.JPEG:jpeg// parameters.setPictureFormat(PixelFormat.JPEG);     // 指定图片为JPEG图片// parameters.set("jpeg-quality", 80);                // 设置图片的质量// PixelFormat.YCbCr_420_SP:NV21,等价于ImageFormat.NV21parameters.setPictureFormat(PixelFormat.YCbCr_420_SP);// (2)setWhiteBalance======================================// autoString whiteBalance = parameters.getWhiteBalance();Log.d(TAG, "whiteBalance:" + whiteBalance);// WHITE_BALANCE_INCANDESCENT:偏蓝// WHITE_BALANCE_FLUORESCENT:偏淡蓝// WHITE_BALANCE_WARM_FLUORESCENT:偏淡蓝// WHITE_BALANCE_DAYLIGHT:日光,正常// WHITE_BALANCE_CLOUDY_DAYLIGHT:阴天,偏黄// WHITE_BALANCE_TWILIGHT:暮光,偏黄// WHITE_BALANCE_SHADE:偏黄parameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_DAYLIGHT);whiteBalance = parameters.getWhiteBalance();Log.d(TAG, "whiteBalance:" + whiteBalance);// (3)setExposureCompensation======================================曝光补偿int minEx = parameters.getMinExposureCompensation();int maxEx = parameters.getMaxExposureCompensation();float stepEx = parameters.getExposureCompensationStep();Log.d(TAG, "minEx:" + minEx + " maxEx:" + maxEx + " stepEx:" + stepEx);parameters.setExposureCompensation(6);// (4)setAutoExposureLock======================================boolean isAELS = parameters.isAutoExposureLockSupported();Log.d(TAG, "isAES:" + isAELS);boolean getAELS = parameters.getAutoExposureLock();Log.d(TAG, "getAES:" + getAELS);parameters.setAutoExposureLock(false);getAELS = parameters.getAutoExposureLock();Log.d(TAG, "getAES:" + getAELS);// (5)setAutoWhiteBalanceLock======================================boolean isAWBLS = parameters.isAutoWhiteBalanceLockSupported();Log.d(TAG, "isAWBLS:" + isAWBLS);boolean getAWBL = parameters.getAutoWhiteBalanceLock();Log.d(TAG, "getAWBL:" + getAWBL);parameters.setAutoWhiteBalanceLock(false);getAWBL = parameters.getAutoWhiteBalanceLock();Log.d(TAG, "getAWBL:" + getAWBL);// (5)setFocusMode======================================String fm = parameters.getFocusMode();Log.d(TAG, "fm:" + fm);// FOCUS_MODE_AUTO:聚焦// FOCUS_MODE_INFINITY:不聚焦// FOCUS_MODE_MACRO:聚焦// FOCUS_MODE_CONTINUOUS_VIDEO:跟随预览的物体远近自动聚焦,afcb返回fail// FOCUS_MODE_CONTINUOUS_PICTURE:跟随预览的物体远近自动聚焦,afcb返回failparameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);fm = parameters.getFocusMode();Log.d(TAG, "fm:" + fm);camera.setParameters(parameters);camera.startPreview();// AF:自动对焦camera.autoFocus(afcb);camera.setDisplayOrientation(90);} catch (IOException e) {e.printStackTrace();}}});ImageButton takePicture = (ImageButton) findViewById(R.id.takephoto);takePicture.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (camera != null) {camera.takePicture(null, null, jpeg);}}});}final Camera.AutoFocusCallback afcb = new Camera.AutoFocusCallback() {@Overridepublic void onAutoFocus(boolean success, Camera camera) {if(success) {// success表示对焦成功Log.d(TAG, "afcb: success");//camera.setOneShotPreviewCallback(null);}else {// 未对焦成功Log.d(TAG, "afcb: fail");}}};// 照片回调函数,实现将照片保存到系统图库中final Camera.PictureCallback jpeg = new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {// 根据拍照所得的数据创建位图final Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);camera.stopPreview();isPreview = false;Log.d(TAG, "Environment.getExternalStorageDirectory():" + Environment.getExternalStorageDirectory());//获取sd卡根目录File appDir = new File(Environment.getExternalStorageDirectory(), "/DCIM/Camera/");if (!appDir.exists()) {      // 如果该目录不存在就创建该目录appDir.mkdir();}String fileName = System.currentTimeMillis() + ".jpg";File file = new File(appDir, fileName);// 保存拍到的图片try {FileOutputStream fos = new FileOutputStream(file);  // 创建一个文件输出流对象boolean ret = bm.compress(Bitmap.CompressFormat.JPEG, 100, fos);  // 将图片内容压缩为JPEG格式输出到输出流对象中Log.d(TAG, "bm.compress ret:" + ret);fos.flush();fos.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}//将照片插入到系统图库try {MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(),file.getAbsolutePath(), fileName, null);} catch (FileNotFoundException e) {e.printStackTrace();}// 最后通知图库更新MainActivity.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.parse("file://" + "")));Toast.makeText(MainActivity.this, "照片保存至:" + file, Toast.LENGTH_LONG).show();resetCamera();}};// 创建resetCamera()方法,实现重新预览功能private void resetCamera() {if (!isPreview) {camera.startPreview();isPreview = true;}}@Overrideprotected void onPause() {if (camera != null) {camera.stopPreview();camera.release();}super.onPause();}
}

查看手机是否安装SD卡:

adb shell mount

adb shell df -h

手机内部存储相册路径:/storage/emulated/0/DCIM/Camera/

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><!--SurfaceView组件--><SurfaceViewandroid:id="@+id/surfaceView"android:layout_width="match_parent"android:layout_height="match_parent" /><!--拍照按钮--><ImageButtonandroid:id="@+id/takephoto"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="right|top"android:layout_marginTop="@dimen/margin_top"android:background="@color/btn_background"android:src="@drawable/camera" /><!--预览按钮--><ImageButtonandroid:id="@+id/preview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="right|bottom"android:layout_marginBottom="@dimen/margin_bottom"android:background="@color/btn_background"android:src="@drawable/preview" /></FrameLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.hyh.camerapreview"><!-- 授予程序可以向SD卡中保存文件的权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><!-- 授予程序使用摄像头的权限 --><uses-permission android:name="android.permission.CAMERA"/><uses-feature android:name="android.hardware.camera.autofocus"/><uses-feature android:name="android.hardware.camera"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.CameraPreview"android:requestLegacyExternalStorage="true"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

2 遇到的问题

2.1 预览时图片拉伸

需要设置预览方向

camera.setDisplayOrientation(90);

2.2 拍照时不能保存相片

java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/1638007179710.jpg: open failed: ENOENT (No such file or directory)

android:requestLegacyExternalStorage="true"

原因是Android10弃用了管理分区外部储存

这篇关于使用摄像头预览和拍照(Camera1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1093710

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

Redis 基本数据类型和使用详解

《Redis基本数据类型和使用详解》String是Redis最基本的数据类型,一个键对应一个值,它的功能十分强大,可以存储字符串、整数、浮点数等多种数据格式,本文给大家介绍Redis基本数据类型和... 目录一、Redis 入门介绍二、Redis 的五大基本数据类型2.1 String 类型2.2 Hash

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三