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

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

相关文章

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4