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

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

相关文章

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当