使用摄像头预览和拍照(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

相关文章

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

使用Python和Pyecharts创建交互式地图

《使用Python和Pyecharts创建交互式地图》在数据可视化领域,创建交互式地图是一种强大的方式,可以使受众能够以引人入胜且信息丰富的方式探索地理数据,下面我们看看如何使用Python和Pyec... 目录简介Pyecharts 简介创建上海地图代码说明运行结果总结简介在数据可视化领域,创建交互式地

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

使用Python实现矢量路径的压缩、解压与可视化

《使用Python实现矢量路径的压缩、解压与可视化》在图形设计和Web开发中,矢量路径数据的高效存储与传输至关重要,本文将通过一个Python示例,展示如何将复杂的矢量路径命令序列压缩为JSON格式,... 目录引言核心功能概述1. 路径命令解析2. 路径数据压缩3. 路径数据解压4. 可视化代码实现详解1