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

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

相关文章

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结