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

news/2024/2/27 16:59:40

参考文章:
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弃用了管理分区外部储存


http://www.ppmy.cn/news/655723.html

相关文章

OCR - 微软windows 11系统自带的Windows OCR功能初体验

一、Power Automate简述 最近再了解一些ocr的相关信息,从一些网站上上看到微软的免费系统实用工具套件中包含ocr识别/pdf文本提取等。 什么是Power Automate? Windows 11 允许用户通过预装的 Power Automate 应用创建自动化。 Power Automate 是一个低代码平台,使家庭和企业…

Win11 首个预览版来了!

本文转载自IT之家 IT之家 6 月 29 日消息 北京时间 6 月 29 日凌晨一点&#xff0c;微软开始向 Win10 Dev 通道的用户推送 Win11 预览版更新。本次更新的版本号为 10.0.22000.51&#xff08;co_release&#xff09;。 IT之家了解到&#xff0c;首个预览版不支持 Android App&a…

Ubuntu apt-get常用命令总结

摘要&#xff1a;apt-get命令是 Ubuntu 系统中的包管理工具&#xff0c;可以用来安装、卸载软件包&#xff0c;也可以用来升级软件包&#xff0c;还可以用来把系统升级到新的版本。本文介绍 apt-get 命令的常见用法&#xff0c;演示环境为 Ubuntu 20.04。 更新软件列表 update…

Vue3 系列:从0开始学习vue3.0

1. vue3.0 和 vue2.0 的区别 我们要学习 vue3&#xff0c;就要知道为什么要学习它&#xff0c;vue3 和 vue2 的区别在哪&#xff0c;对于我们开发的优势在哪。 vue3.0 与 2020/9/18 正式发布&#xff0c;vue2.0 与 2023/12/31 日停止维护。 1.1 双向数据绑定原理 vue2: es5 …

教育部最新通知,中高考又有大变化,学生欲哭无泪,家长炸锅了

教育部最新通知&#xff0c;中高考又有大变化&#xff0c;学生欲哭无泪&#xff0c;家长炸锅了&#xff01; 近年来我国教育事业发展非常迅速&#xff0c;特别是信息化时代的到来&#xff0c;孩子的学习环境发生了翻天覆地的变化&#xff0c;比如这次疫情&#xff0c;如果不是…

微信「炸一炸」靠什么「振撼全场」?

来源&#xff5c;36氪 文&#xff5c;汝晴 Lina ▲IC photo 微信又双叒更新了&#xff0c;5月17日&#xff0c;微信发布了iOS8.0.6正式版&#xff0c;更新了多项功能&#xff0c;其中就包括“拍一拍”基础之上的“炸一炸”。 只需简单在“拍一拍”设置中添加会动的表情&#xf…

餐饮巨头被攻击的“致命”48小时

编者按 数字化浪潮蓬勃兴起&#xff0c;企业面临的安全挑战亦日益严峻。 腾讯安全近期将复盘2022年典型的攻击事件&#xff0c;帮助企业深入了解攻击手法和应对措施&#xff0c;完善自身安全防御体系。 本篇是第八期&#xff0c;讲述了某餐饮巨头遭遇黑客多轮次攻击、全国点餐系…

IE 今天正式停用!网友炸锅了

&#x1f447;&#x1f447;关注后回复 “进群” &#xff0c;拉你进程序员交流群&#x1f447;&#x1f447; 作者丨鱼皮 来源丨程序员鱼皮&#xff08;ID&#xff1a;coder_yupi&#xff09; 大家好&#xff0c;我是鱼皮&#xff0c;昨天一条消息冲上热搜&#xff0c;如图: 其…

B站机房失火导致网站崩溃?网络工程师又又又背锅了……

昨晚我正准备拿出手机看看&#xff0c;就发现咱们网工交流群里有群友喊“b站崩了”。 听说这次故障持续了一个多小时&#xff0c;因为B站没得看&#xff0c;网友又跑去A站看&#xff0c;这下A站也崩了&#xff0c;网友更崩溃了。 本来想着也没多大事儿&#xff0c;但是这次引起…

七夕的朋友圈 —— 炸锅了

大事件 今早起来&#xff0c;逛逛朋友圈&#xff0c;看到的全是各种秀。唉&#xff0c;图片咱就不放了&#xff0c;难免戳中某位朋友瘦小的心灵&#xff0c;主要我也怕&#xff0c;你们知道叭。 这种时候怎么能让我们的朋友圈是白茫茫的一片呢&#xff1f;必须怼回去&#xff…

DDOS攻击的那些事

在互联网中一谈起DDOS攻击&#xff0c;人们往往谈虎色变。DDOS攻击被认为是安全领域最难解决的问题之一&#xff0c;迄今为止也没有一个完美的解决方案。各个互联网公司都等着5G时代的来临&#xff0c;等它来临分物联网领域的一份羹。当物联网时代真正来临的时候&#xff0c;网…

网络冷知识

IP 协议中header长度范围 答案&#xff1a;20字节-60字节 网络协议 (IP协议) 在 RFC 791 中定义。RFC 指定 IP 报头的格式。 在报头中有一个 4 位长的 IHL&#xff08;互联网报头长度&#xff09;字段&#xff0c;并以 32 位字指定报头长度。 IHL 字段可以保存从 0&#xff0…

“商量”翻车了?网友质疑搬运C站

在ChatGPT大热的当下&#xff0c;各大互联网和AI大厂陆续开始推出国内版本的大模型产品了&#xff0c;最近发布的有&#xff1a; 商汤版ChatGPT发布千亿参数大模型&#xff1a;商量&#xff01;第一个真正实现智能涌现的国产大语言模型&#xff0c;内测即将开启阿里版 ChatGPT …

炸锅了!IDC预测槽点满满,劝管理员和运维人员早作打算!

最近&#xff0c;外媒Register发布了一则新闻&#xff1a;分析公司IDC预测&#xff0c;担任系统管理员和IT运维专职的人数将大幅下降&#xff0c;希望这些从业者重新考虑他们的职业生涯。 孰料&#xff0c;一石激起千层浪&#xff0c;引发了大量争议。 事件回顾&#xff1a;一…

如何防御恶意流量攻击(CC、DDoS)?

随之网络安全的地位不断提高&#xff0c;越来越多的攻击得以解决&#xff0c;但随之而来的也是新的攻击在变着花样地出现&#xff0c;就好比DDoS攻击与CC攻击就是这些年较为常见的攻击手段&#xff0c;这两种攻击分别针对网站的应用层和网络层。 我们网站运维人员一定要做好功课…

Log4j爆核弹级漏洞,大厂中招、公司炸锅了...

作者&#xff1a;研磨架构 出处&#xff1a;https://www.zhihu.com/question/505025655/answer/2265086040 这周&#xff0c;很多 Java 程序员都忙疯了&#xff0c;因为只要是 Java 程序员&#xff0c;几乎都会用到 Apache Log4j 这个组建。 但这个组建却爆出来一个史诗级的 Bu…

一文读懂|栈溢出攻击

什么是栈 简单来说&#xff0c;栈 是一种 LIFO&#xff08;Last In Frist Out&#xff0c;后进先出&#xff09; 形式的数据结构。栈一般是从高地址向低地址增长&#xff0c;并且栈支持 push&#xff08;入栈&#xff09; 和 pop&#xff08;出栈&#xff09; 两个操作。如下图…

网络攻击损失不容小觑

据研究数据显示&#xff0c;2022年数据泄露给企业造成的平均损失为435万美元&#xff1b;如果是勒索软件攻击&#xff0c;损失将增加到454万美元。当然这只是估计&#xff0c;在某些国家或地区平均损失更高&#xff0c;比如在美国&#xff0c;损失接近1000万美元。 此外&#x…

爆炸了!但YYDS

正文共&#xff1a; 2962字 预计阅读时间&#xff1a; 8分钟 成功发射&#xff0c;但在空中爆炸了。 这一刻&#xff0c;我们都仰望星空。 北京时间 4 月 20 日晚 9 点半&#xff0c;随着倒计时声音的结束&#xff0c;在 SpaceX 位于得州的发射基地&#xff0c;一艘比自由女神像…

韩国大面积断网事情,可能遭受了DDoS攻击,网友:真的是黑客攻击吗?

大家好&#xff0c;我是辣条。 昨天刷微博看到一个热搜爆了&#xff0c;韩国竟然出现大面积断网事情&#xff0c;重要的是官方发布可能是遭受到了DDoS攻击&#xff0c;这就吸引到我的兴趣了。 这个事情对韩国影响还是很大的&#xff0c;各行各业都遭受很大的冲击&#xff0c;甚…
最新文章