自定义相机,使用前置摄像头实现自拍

2024-03-07 12:48

本文主要是介绍自定义相机,使用前置摄像头实现自拍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通过Camera.open()获取相机,实现自定义自拍功能。

demo比较简单,直接上代码:

Activity


public class MainActivity extends AppCompatActivity {SurfaceView sView;SurfaceHolder surfaceHodler;int screenWidth, screenHeight;// 定义系统所用的照相机Camera camera;// 是否存在预览中boolean isPreview = false;private String filepath = "";//照片保存路径@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 获取窗口管理器WindowManager wm = getWindowManager();Display display = wm.getDefaultDisplay();DisplayMetrics metrics = new DisplayMetrics();// 获取屏幕的宽和高display.getMetrics(metrics);screenWidth = metrics.widthPixels;screenHeight = metrics.heightPixels;sView = (SurfaceView) findViewById(R.id.sView);// 设置surface不需要自己的维护缓存区sView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 获得SurfaceView的SurfaceHoldersurfaceHodler = sView.getHolder();// 为srfaceHolder添加一个回调监听器surfaceHodler.addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceDestroyed(SurfaceHolder arg0) {// 如果camera不为null,释放摄像头System.out.println("释放摄像头");if (camera != null) {if (isPreview)camera.stopPreview();camera.release();camera = null;isPreview = false;}}@Overridepublic void surfaceCreated(SurfaceHolder arg0) {System.out.println("打开摄像头");// 打开摄像头initCamera();}@Overridepublic void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,int arg3) {System.out.println("摄像头改变");}});}public void capture(View source) {sView.setVisibility(View.VISIBLE);}private void initCamera() {if (!isPreview) {// 此处默认打开后置摄像头// 通过传入参数可以打开前置摄像头camera = openFrontFacingCameraGingerbread();}if (!isPreview && camera != null) {Camera.Parameters parameters = camera.getParameters();// 设置预览照片的大小parameters.setPreviewSize(screenWidth, screenHeight);// 设置预览照片时每秒显示多少帧的最小值和最大值parameters.setPreviewFpsRange(4, 10);// 设置照片的格式parameters.setPictureFormat(ImageFormat.JPEG);parameters.setPreviewSize(800, 480);//图片大小// 设置JPG照片的质量parameters.set("jpeg-quality", 100);// 设置照片的大小parameters.setPictureSize(screenWidth, screenHeight);// 通过SurfaceView显示取景画面try {camera.setPreviewDisplay(surfaceHodler);// 系统相机默认是横屏的,我们要旋转90°camera.setDisplayOrientation(90);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 开始预览camera.startPreview();isPreview = true;new Handler().postDelayed(new Runnable() {@Overridepublic void run() {if (camera != null) {System.out.println("控制摄像头自动对焦后才拍摄");// 控制摄像头自动对焦后才拍摄//camera.autoFocus(autoFocusCallback);//关闭声音setCameraSound(true);camera.takePicture(new Camera.ShutterCallback() {@Overridepublic void onShutter() {// 按下快门瞬间会执行此处代码}}, new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] arg0, Camera arg1) {// 此处代码可以决定是否需要保存原始照片信息}}, jpeg);}}}, 1000);}}private Camera openFrontFacingCameraGingerbread() {int cameraCount = 0;Camera cam = null;Camera.CameraInfo cameraInfo = new Camera.CameraInfo();cameraCount = Camera.getNumberOfCameras();System.out.println("cameraCount = "+cameraCount);for (int camIdx = 0; camIdx < cameraCount; camIdx++) {Camera.getCameraInfo(camIdx, cameraInfo);if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {try {cam = Camera.open(camIdx);} catch (RuntimeException e) {Log.e("", "Camera failed to open: " + e.getLocalizedMessage());}}}System.out.println("获取摄像头");if (cam == null)System.out.println("摄像头获取失败");return cam;}Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {@Overridepublic void onAutoFocus(boolean arg0, Camera arg1) {if (arg0) {//关闭声音setCameraSound(true);// takePicture()方法需要传入三个监听参数// 第一个监听器;当用户按下快门时激发该监听器// 第二个监听器;当相机获取原始照片时激发该监听器// 第三个监听器;当相机获取JPG照片时激发该监听器System.out.println("拍照");camera.takePicture(new Camera.ShutterCallback() {@Overridepublic void onShutter() {// 按下快门瞬间会执行此处代码}}, new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] arg0, Camera arg1) {// 此处代码可以决定是否需要保存原始照片信息}}, jpeg);new Handler().postDelayed(new Runnable() {@Overridepublic void run() {//  sView.setVisibility(View.GONE);//}}, 1000);} else {System.out.println("对焦失败,不拍照");}}};//创建jpeg图片回调数据对象Camera.PictureCallback jpeg = new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {// TODO Auto-generated method stubtry {Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);// 创建一个位于SD卡上的文件File file = new File(Environment.getExternalStorageDirectory() + File.separator + "aaa");if (!file.exists()) {file.mkdir();}file = new File(file, System.currentTimeMillis() + ".jpg");FileOutputStream fileOutStream = null;try {fileOutStream = new FileOutputStream(file);//把位图输出到指定的文件中bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutStream);fileOutStream.close();} catch (IOException io) {io.printStackTrace();}camera.stopPreview();//关闭预览 处理数据camera.startPreview();//数据处理完后继续开始预览bitmap.recycle();//回收bitmap空间isPreview = true;//关闭预览框,回复声音sView.setVisibility(View.GONE);setCameraSound(false);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}};private void setCameraSound(final boolean isSound) {new Thread(new Runnable() {@Overridepublic void run() {AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);audioManager.setStreamMute(AudioManager.STREAM_SYSTEM, isSound);}}).start();}
}

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:orientation="vertical"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.jin.activity.MainActivity"><SurfaceView
        android:id="@+id/sView"android:layout_width="80dp"android:layout_height="100dp"android:layout_alignParentRight="true"android:visibility="gone"></SurfaceView><Button
        android:id="@+id/take"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:onClick="capture"android:text="开门"></Button></RelativeLayout>

注:
经过测试发现7.0以下手机没问题,而7.0系统手机在Camera.open()出现Camera failed to open: Fail to connect to camera service,就是获取不到相机服务无法打开相机,需要手动在手机设置里面打开相机权限,即可正常使用。因此可以加一个判断:

//判断系统版本大于23,即247.0)和以上版本提示打开权限if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {}

这篇关于自定义相机,使用前置摄像头实现自拍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python 字典 (Dictionary)使用详解

《Python字典(Dictionary)使用详解》字典是python中最重要,最常用的数据结构之一,它提供了高效的键值对存储和查找能力,:本文主要介绍Python字典(Dictionary)... 目录字典1.基本特性2.创建字典3.访问元素4.修改字典5.删除元素6.字典遍历7.字典的高级特性默认字典

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

python生成随机唯一id的几种实现方法

《python生成随机唯一id的几种实现方法》在Python中生成随机唯一ID有多种方法,根据不同的需求场景可以选择最适合的方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习... 目录方法 1:使用 UUID 模块(推荐)方法 2:使用 Secrets 模块(安全敏感场景)方法

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态